diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 4d7db6393b..7aedc9b1ae 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -40,9 +40,10 @@ BEOS_BIN = "[" addattr alert arp base64 basename bc beep bootman bzip2 gawk $(X86_ONLY)gdb grep groups gzip gzexe hd head hey hostname id ident ideinfo idestatus ifconfig install installsound iroster isvolume join keymap kill less lessecho lesskey link listarea listattr listimage listdev - listport listres listsem ln locate logger login logname ls lsindex m4 make - makebootable md5sum merge mimeset mkdos mkdir mkfifo mkfs mkindex modifiers - mount mount_nfs mountvolume mv nc netstat nl nohup od open passwd paste + listport listres listsem ln locate logger login logname ls lsindex + make makebootable md5sum merge mimeset mkdos mkdir mkfifo mkfs mkindex + modifiers mount mount_nfs mountvolume mv + nc netstat nl nohup od open passwd paste patch pathchk pc ping play playfile playsound playwav pr prio printenv printf profile ps ptx pwd query quit rc readlink release renice rescan rlog rm rmattr rmindex rmdir roster route diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 025907d24c..ab64f7f5f9 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -236,8 +236,11 @@ if [ IsOptionalHaikuImagePackageAdded Development ] : $(baseURL)/gcc-2.95.3-haiku-081024.zip : ; - # other tools + InstallOptionalHaikuImagePackage m4-1.4.12-gcc2-2008-11-04 + : $(baseURL)/m4-1.4.12-gcc2-2008-11-04.zip + : + ; InstallOptionalHaikuImagePackage autoconf-2.61-gcc2-2008-03-24 : $(baseURL)/autoconf-2.61-gcc2-2008-03-24.zip : home diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 19129b6102..78188075c4 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -189,7 +189,6 @@ SubInclude HAIKU_TOP src bin ideinfo ; SubInclude HAIKU_TOP src bin keymap ; SubInclude HAIKU_TOP src bin less ; SubInclude HAIKU_TOP src bin listdev ; -SubInclude HAIKU_TOP src bin m4 ; SubInclude HAIKU_TOP src bin make ; SubInclude HAIKU_TOP src bin makebootable ; #SubInclude HAIKU_TOP src bin makeudfimage ; diff --git a/src/bin/m4/COPYING b/src/bin/m4/COPYING deleted file mode 100644 index d511905c16..0000000000 --- a/src/bin/m4/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) 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 -this service 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 make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. 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. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -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 -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the 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 a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE 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. - - 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 -convey 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 2 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, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision 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, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This 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. diff --git a/src/bin/m4/Jamfile b/src/bin/m4/Jamfile deleted file mode 100644 index be30672b1a..0000000000 --- a/src/bin/m4/Jamfile +++ /dev/null @@ -1,5 +0,0 @@ -SubDir HAIKU_TOP src bin m4 ; - -SubInclude HAIKU_TOP src bin m4 lib ; -SubInclude HAIKU_TOP src bin m4 src ; - diff --git a/src/bin/m4/doc/Makefile.am b/src/bin/m4/doc/Makefile.am deleted file mode 100644 index 9e2dacf560..0000000000 --- a/src/bin/m4/doc/Makefile.am +++ /dev/null @@ -1,43 +0,0 @@ -## This file is part of GNU M4. -## -## Copyright (C) 2006 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 2 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; see the file COPYING. If not, write to -## the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -## Boston, MA 02110-1301, USA. -## -## This file written by Eric Blake - -info_TEXINFOS = m4.texinfo -m4_TEXINFOS = fdl.texi -man_MANS = m4.1 -EXTRA_DIST = $(man_MANS) gendocs_template -MAINTAINERCLEANFILES = $(man_MANS) gendocs_template -SUFFIXES = .1 - -# Depend on configure.ac for version, m4.c for usage text. Do not depend on -# built m4 executable, since not everyone has help2man or perl. -# 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)/configure.ac $(top_srcdir)/src/m4.c - @if test -x ../src/m4$(EXEEXT) ; then \ - echo "Updating man page m4.1" ; \ - $(SHELL) $(top_srcdir)/missing --run \ - help2man --name="macro processor" --source=FSF \ - --info-page=m4 --output=$@ ../src/m4$(EXEEXT) ; \ - else \ - echo "WARNING: The \`man' page \`$@' cannot be updated yet."; \ - echo " Retry once the program executable is ready."; \ - fi diff --git a/src/bin/m4/doc/Makefile.in b/src/bin/m4/doc/Makefile.in deleted file mode 100644 index 69183b5788..0000000000 --- a/src/bin/m4/doc/Makefile.in +++ /dev/null @@ -1,708 +0,0 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This Makefile.in 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. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = doc -DIST_COMMON = $(m4_TEXINFOS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/stamp-vti \ - $(srcdir)/version.texi mdate-sh texinfo.tex -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ - $(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/allocsa.m4 \ - $(top_srcdir)/m4/cloexec.m4 $(top_srcdir)/m4/close-stream.m4 \ - $(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/config-h.m4 $(top_srcdir)/m4/eealloc.m4 \ - $(top_srcdir)/m4/eoverflow.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/fatal-signal.m4 $(top_srcdir)/m4/fpending.m4 \ - $(top_srcdir)/m4/free.m4 $(top_srcdir)/m4/getopt.m4 \ - $(top_srcdir)/m4/gl_list.m4 $(top_srcdir)/m4/gnulib-comp.m4 \ - $(top_srcdir)/m4/inline.m4 $(top_srcdir)/m4/intmax_t.m4 \ - $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/longdouble.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mbchar.m4 \ - $(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \ - $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/memchr.m4 \ - $(top_srcdir)/m4/mkdtemp.m4 $(top_srcdir)/m4/mkstemp.m4 \ - $(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/quotearg.m4 \ - $(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/sig_atomic_t.m4 \ - $(top_srcdir)/m4/signalblocking.m4 \ - $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/ssize_t.m4 \ - $(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \ - $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ - $(top_srcdir)/m4/stdio-safer.m4 \ - $(top_srcdir)/m4/stdlib-safer.m4 $(top_srcdir)/m4/strcase.m4 \ - $(top_srcdir)/m4/strstr.m4 $(top_srcdir)/m4/strtol.m4 \ - $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/tempname.m4 \ - $(top_srcdir)/m4/tmpdir.m4 $(top_srcdir)/m4/ulonglong.m4 \ - $(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \ - $(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/vasnprintf.m4 \ - $(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wcwidth.m4 $(top_srcdir)/m4/wint_t.m4 \ - $(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/m4/xvasprintf.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/config.h -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -INFO_DEPS = $(srcdir)/m4.info -am__TEXINFO_TEX_DIR = $(srcdir) -DVIS = m4.dvi -PDFS = m4.pdf -PSS = m4.ps -HTMLS = m4.html -TEXINFOS = m4.texinfo -TEXI2DVI = texi2dvi -TEXI2PDF = $(TEXI2DVI) --pdf --batch -MAKEINFOHTML = $(MAKEINFO) --html -AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) -DVIPS = dvips -am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)" -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -man1dir = $(mandir)/man1 -NROFF = nroff -MANS = $(man_MANS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ABSOLUTE_STDINT_H = @ABSOLUTE_STDINT_H@ -ABSOLUTE_SYS_STAT_H = @ABSOLUTE_SYS_STAT_H@ -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -ALLOCA_H = @ALLOCA_H@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ -BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ -BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ -BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ -BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EOVERFLOW = @EOVERFLOW@ -EXEEXT = @EXEEXT@ -GETOPT_H = @GETOPT_H@ -GREP = @GREP@ -HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ -HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ -HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ -HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ -HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ -HAVE_STDINT_H = @HAVE_STDINT_H@ -HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ -HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ -HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ -HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ -HAVE_WCHAR_H = @HAVE_WCHAR_H@ -HAVE__BOOL = @HAVE__BOOL@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBM4_LIBDEPS = @LIBM4_LIBDEPS@ -LIBM4_LTLIBDEPS = @LIBM4_LTLIBDEPS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -M4_LIBOBJS = @M4_LIBOBJS@ -M4_LTLIBOBJS = @M4_LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ -SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ -STDBOOL_H = @STDBOOL_H@ -STDINT_H = @STDINT_H@ -STRIP = @STRIP@ -SYS_STAT_H = @SYS_STAT_H@ -UNISTD_H = @UNISTD_H@ -VERSION = @VERSION@ -WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ -WINT_T_SUFFIX = @WINT_T_SUFFIX@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -info_TEXINFOS = m4.texinfo -m4_TEXINFOS = fdl.texi -man_MANS = m4.1 -EXTRA_DIST = $(man_MANS) gendocs_template -MAINTAINERCLEANFILES = $(man_MANS) gendocs_template -SUFFIXES = .1 -all: all-am - -.SUFFIXES: -.SUFFIXES: .1 .dvi .html .info .pdf .ps .texinfo -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu doc/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -.texinfo.info: - restore=: && backupdir="$(am__leading_dot)am$$$$" && \ - am__cwd=`pwd` && cd $(srcdir) && \ - rm -rf $$backupdir && mkdir $$backupdir && \ - if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ - for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ - if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ - done; \ - else :; fi && \ - cd "$$am__cwd"; \ - if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ - -o $@ $<; \ - then \ - rc=0; \ - cd $(srcdir); \ - else \ - rc=$$?; \ - cd $(srcdir) && \ - $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ - fi; \ - rm -rf $$backupdir; exit $$rc - -.texinfo.dvi: - TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ - MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ - $(TEXI2DVI) $< - -.texinfo.pdf: - TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ - MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ - $(TEXI2PDF) $< - -.texinfo.html: - rm -rf $(@:.html=.htp) - if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ - -o $(@:.html=.htp) $<; \ - then \ - rm -rf $@; \ - if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ - mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ - else \ - if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ - rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ - exit 1; \ - fi -$(srcdir)/m4.info: m4.texinfo $(srcdir)/version.texi $(m4_TEXINFOS) -m4.dvi: m4.texinfo $(srcdir)/version.texi $(m4_TEXINFOS) -m4.pdf: m4.texinfo $(srcdir)/version.texi $(m4_TEXINFOS) -m4.html: m4.texinfo $(srcdir)/version.texi $(m4_TEXINFOS) -$(srcdir)/version.texi: $(srcdir)/stamp-vti -$(srcdir)/stamp-vti: m4.texinfo $(top_srcdir)/configure - @(dir=.; test -f ./m4.texinfo || dir=$(srcdir); \ - set `$(SHELL) $(srcdir)/mdate-sh $$dir/m4.texinfo`; \ - echo "@set UPDATED $$1 $$2 $$3"; \ - echo "@set UPDATED-MONTH $$2 $$3"; \ - echo "@set EDITION $(VERSION)"; \ - echo "@set VERSION $(VERSION)") > vti.tmp - @cmp -s vti.tmp $(srcdir)/version.texi \ - || (echo "Updating $(srcdir)/version.texi"; \ - cp vti.tmp $(srcdir)/version.texi) - -@rm -f vti.tmp - @cp $(srcdir)/version.texi $@ - -mostlyclean-vti: - -rm -f vti.tmp - -maintainer-clean-vti: - -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi -.dvi.ps: - TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ - $(DVIPS) -o $@ $< - -uninstall-dvi-am: - @$(NORMAL_UNINSTALL) - @list='$(DVIS)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ - rm -f "$(DESTDIR)$(dvidir)/$$f"; \ - done - -uninstall-html-am: - @$(NORMAL_UNINSTALL) - @list='$(HTMLS)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ - rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ - done - -uninstall-info-am: - @$(PRE_UNINSTALL) - @if test -d '$(DESTDIR)$(infodir)' && \ - (install-info --version && \ - install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ - list='$(INFO_DEPS)'; \ - for file in $$list; do \ - relfile=`echo "$$file" | sed 's|^.*/||'`; \ - echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ - install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ - done; \ - else :; fi - @$(NORMAL_UNINSTALL) - @list='$(INFO_DEPS)'; \ - for file in $$list; do \ - relfile=`echo "$$file" | sed 's|^.*/||'`; \ - relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ - (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ - echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ - rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ - else :; fi); \ - done - -uninstall-pdf-am: - @$(NORMAL_UNINSTALL) - @list='$(PDFS)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ - rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ - done - -uninstall-ps-am: - @$(NORMAL_UNINSTALL) - @list='$(PSS)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ - rm -f "$(DESTDIR)$(psdir)/$$f"; \ - done - -dist-info: $(INFO_DEPS) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - list='$(INFO_DEPS)'; \ - for base in $$list; do \ - case $$base in \ - $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ - esac; \ - if test -f $$base; then d=.; else d=$(srcdir); fi; \ - base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ - for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ - if test -f $$file; then \ - relfile=`expr "$$file" : "$$d/\(.*\)"`; \ - test -f $(distdir)/$$relfile || \ - cp -p $$file $(distdir)/$$relfile; \ - else :; fi; \ - done; \ - done - -mostlyclean-aminfo: - -rm -rf m4.aux m4.cp m4.cps m4.fn m4.fns m4.ky m4.kys m4.log m4.pg m4.pgs \ - m4.tmp m4.toc m4.tp m4.tps m4.vr m4.vrs m4.dvi m4.pdf m4.ps \ - m4.html - -maintainer-clean-aminfo: - @list='$(INFO_DEPS)'; for i in $$list; do \ - i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ - echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ - rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ - done -install-man1: $(man1_MANS) $(man_MANS) - @$(NORMAL_INSTALL) - test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" - @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ - l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ - for i in $$l2; do \ - case "$$i" in \ - *.1*) list="$$list $$i" ;; \ - esac; \ - done; \ - for i in $$list; do \ - if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ - else file=$$i; fi; \ - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - case "$$ext" in \ - 1*) ;; \ - *) ext='1' ;; \ - esac; \ - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ - done -uninstall-man1: - @$(NORMAL_UNINSTALL) - @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ - l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ - for i in $$l2; do \ - case "$$i" in \ - *.1*) list="$$list $$i" ;; \ - esac; \ - done; \ - for i in $$list; do \ - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - case "$$ext" in \ - 1*) ;; \ - *) ext='1' ;; \ - esac; \ - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ - rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-info -check-am: all-am -check: check-am -all-am: Makefile $(INFO_DEPS) $(MANS) -installdirs: - for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: $(DVIS) - -html: html-am - -html-am: $(HTMLS) - -info: info-am - -info-am: $(INFO_DEPS) - -install-data-am: install-info-am install-man - -install-dvi: install-dvi-am - -install-dvi-am: $(DVIS) - @$(NORMAL_INSTALL) - test -z "$(dvidir)" || $(MKDIR_P) "$(DESTDIR)$(dvidir)" - @list='$(DVIS)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(dvidir)/$$f'"; \ - $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(dvidir)/$$f"; \ - done -install-exec-am: - -install-html: install-html-am - -install-html-am: $(HTMLS) - @$(NORMAL_INSTALL) - test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)" - @list='$(HTMLS)'; for p in $$list; do \ - if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - if test -d "$$d$$p"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ - $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ - echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \ - $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \ - else \ - echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \ - $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \ - fi; \ - done -install-info: install-info-am - -install-info-am: $(INFO_DEPS) - @$(NORMAL_INSTALL) - test -z "$(infodir)" || $(MKDIR_P) "$(DESTDIR)$(infodir)" - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - list='$(INFO_DEPS)'; \ - for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - esac; \ - if test -f $$file; then d=.; else d=$(srcdir); fi; \ - file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ - for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ - $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ - if test -f $$ifile; then \ - relfile=`echo "$$ifile" | sed 's|^.*/||'`; \ - echo " $(INSTALL_DATA) '$$ifile' '$(DESTDIR)$(infodir)/$$relfile'"; \ - $(INSTALL_DATA) "$$ifile" "$(DESTDIR)$(infodir)/$$relfile"; \ - else : ; fi; \ - done; \ - done - @$(POST_INSTALL) - @if (install-info --version && \ - install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ - list='$(INFO_DEPS)'; \ - for file in $$list; do \ - relfile=`echo "$$file" | sed 's|^.*/||'`; \ - echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ - install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ - done; \ - else : ; fi -install-man: install-man1 - -install-pdf: install-pdf-am - -install-pdf-am: $(PDFS) - @$(NORMAL_INSTALL) - test -z "$(pdfdir)" || $(MKDIR_P) "$(DESTDIR)$(pdfdir)" - @list='$(PDFS)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/$$f'"; \ - $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/$$f"; \ - done -install-ps: install-ps-am - -install-ps-am: $(PSS) - @$(NORMAL_INSTALL) - test -z "$(psdir)" || $(MKDIR_P) "$(DESTDIR)$(psdir)" - @list='$(PSS)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(psdir)/$$f'"; \ - $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(psdir)/$$f"; \ - done -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-aminfo \ - maintainer-clean-generic maintainer-clean-vti - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-aminfo mostlyclean-generic mostlyclean-vti - -pdf: pdf-am - -pdf-am: $(PDFS) - -ps: ps-am - -ps-am: $(PSS) - -uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ - uninstall-man uninstall-pdf-am uninstall-ps-am - -uninstall-man: uninstall-man1 - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic dist-info \ - distclean distclean-generic distdir dvi dvi-am html html-am \ - info info-am install install-am install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-man1 install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-aminfo \ - maintainer-clean-generic maintainer-clean-vti mostlyclean \ - mostlyclean-aminfo mostlyclean-generic mostlyclean-vti pdf \ - pdf-am ps ps-am uninstall uninstall-am uninstall-dvi-am \ - uninstall-html-am uninstall-info-am uninstall-man \ - uninstall-man1 uninstall-pdf-am uninstall-ps-am - - -# Depend on configure.ac for version, m4.c for usage text. Do not depend on -# built m4 executable, since not everyone has help2man or perl. -# 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)/configure.ac $(top_srcdir)/src/m4.c - @if test -x ../src/m4$(EXEEXT) ; then \ - echo "Updating man page m4.1" ; \ - $(SHELL) $(top_srcdir)/missing --run \ - help2man --name="macro processor" --source=FSF \ - --info-page=m4 --output=$@ ../src/m4$(EXEEXT) ; \ - else \ - echo "WARNING: The \`man' page \`$@' cannot be updated yet."; \ - echo " Retry once the program executable is ready."; \ - fi -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/bin/m4/doc/fdl.texi b/src/bin/m4/doc/fdl.texi deleted file mode 100644 index 9c6d9afe3f..0000000000 --- a/src/bin/m4/doc/fdl.texi +++ /dev/null @@ -1,452 +0,0 @@ - -@node GNU Free Documentation License -@appendixsec GNU Free Documentation License - -@cindex FDL, GNU Free Documentation License -@center Version 1.2, November 2002 - -@display -Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. -51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. -@end display - -@enumerate 0 -@item -PREAMBLE - -The purpose of this License is to make a manual, textbook, or other -functional and useful document @dfn{free} in the sense of freedom: to -assure everyone the effective freedom to copy and redistribute it, -with or without modifying it, either commercially or noncommercially. -Secondarily, this License preserves for the author and publisher a way -to get credit for their work, while not being considered responsible -for modifications made by others. - -This License is a kind of ``copyleft'', which means that derivative -works of the document must themselves be free in the same sense. It -complements the GNU General Public License, which is a copyleft -license designed for free software. - -We have designed this License in order to use it for manuals for free -software, because free software needs free documentation: a free -program should come with manuals providing the same freedoms that the -software does. But this License is not limited to software manuals; -it can be used for any textual work, regardless of subject matter or -whether it is published as a printed book. We recommend this License -principally for works whose purpose is instruction or reference. - -@item -APPLICABILITY AND DEFINITIONS - -This License applies to any manual or other work, in any medium, that -contains a notice placed by the copyright holder saying it can be -distributed under the terms of this License. Such a notice grants a -world-wide, royalty-free license, unlimited in duration, to use that -work under the conditions stated herein. The ``Document'', below, -refers to any such manual or work. Any member of the public is a -licensee, and is addressed as ``you''. You accept the license if you -copy, modify or distribute the work in a way requiring permission -under copyright law. - -A ``Modified Version'' of the Document means any work containing the -Document or a portion of it, either copied verbatim, or with -modifications and/or translated into another language. - -A ``Secondary Section'' is a named appendix or a front-matter section -of the Document that deals exclusively with the relationship of the -publishers or authors of the Document to the Document's overall -subject (or to related matters) and contains nothing that could fall -directly within that overall subject. (Thus, if the Document is in -part a textbook of mathematics, a Secondary Section may not explain -any mathematics.) The relationship could be a matter of historical -connection with the subject or with related matters, or of legal, -commercial, philosophical, ethical or political position regarding -them. - -The ``Invariant Sections'' are certain Secondary Sections whose titles -are designated, as being those of Invariant Sections, in the notice -that says that the Document is released under this License. If a -section does not fit the above definition of Secondary then it is not -allowed to be designated as Invariant. The Document may contain zero -Invariant Sections. If the Document does not identify any Invariant -Sections then there are none. - -The ``Cover Texts'' are certain short passages of text that are listed, -as Front-Cover Texts or Back-Cover Texts, in the notice that says that -the Document is released under this License. A Front-Cover Text may -be at most 5 words, and a Back-Cover Text may be at most 25 words. - -A ``Transparent'' copy of the Document means a machine-readable copy, -represented in a format whose specification is available to the -general public, that is suitable for revising the document -straightforwardly with generic text editors or (for images composed of -pixels) generic paint programs or (for drawings) some widely available -drawing editor, and that is suitable for input to text formatters or -for automatic translation to a variety of formats suitable for input -to text formatters. A copy made in an otherwise Transparent file -format whose markup, or absence of markup, has been arranged to thwart -or discourage subsequent modification by readers is not Transparent. -An image format is not Transparent if used for any substantial amount -of text. A copy that is not ``Transparent'' is called ``Opaque''. - -Examples of suitable formats for Transparent copies include plain -@sc{ascii} without markup, Texinfo input format, La@TeX{} input -format, @acronym{SGML} or @acronym{XML} using a publicly available -@acronym{DTD}, and standard-conforming simple @acronym{HTML}, -PostScript or @acronym{PDF} designed for human modification. Examples -of transparent image formats include @acronym{PNG}, @acronym{XCF} and -@acronym{JPG}. Opaque formats include proprietary formats that can be -read and edited only by proprietary word processors, @acronym{SGML} or -@acronym{XML} for which the @acronym{DTD} and/or processing tools are -not generally available, and the machine-generated @acronym{HTML}, -PostScript or @acronym{PDF} produced by some word processors for -output purposes only. - -The ``Title Page'' means, for a printed book, the title page itself, -plus such following pages as are needed to hold, legibly, the material -this License requires to appear in the title page. For works in -formats which do not have any title page as such, ``Title Page'' means -the text near the most prominent appearance of the work's title, -preceding the beginning of the body of the text. - -A section ``Entitled XYZ'' means a named subunit of the Document whose -title either is precisely XYZ or contains XYZ in parentheses following -text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as ``Acknowledgements'', -``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' -of such a section when you modify the Document means that it remains a -section ``Entitled XYZ'' according to this definition. - -The Document may include Warranty Disclaimers next to the notice which -states that this License applies to the Document. These Warranty -Disclaimers are considered to be included by reference in this -License, but only as regards disclaiming warranties: any other -implication that these Warranty Disclaimers may have is void and has -no effect on the meaning of this License. - -@item -VERBATIM COPYING - -You may copy and distribute the Document in any medium, either -commercially or noncommercially, provided that this License, the -copyright notices, and the license notice saying this License applies -to the Document are reproduced in all copies, and that you add no other -conditions whatsoever to those of this License. You may not use -technical measures to obstruct or control the reading or further -copying of the copies you make or distribute. However, you may accept -compensation in exchange for copies. If you distribute a large enough -number of copies you must also follow the conditions in section 3. - -You may also lend copies, under the same conditions stated above, and -you may publicly display copies. - -@item -COPYING IN QUANTITY - -If you publish printed copies (or copies in media that commonly have -printed covers) of the Document, numbering more than 100, and the -Document's license notice requires Cover Texts, you must enclose the -copies in covers that carry, clearly and legibly, all these Cover -Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on -the back cover. Both covers must also clearly and legibly identify -you as the publisher of these copies. The front cover must present -the full title with all words of the title equally prominent and -visible. You may add other material on the covers in addition. -Copying with changes limited to the covers, as long as they preserve -the title of the Document and satisfy these conditions, can be treated -as verbatim copying in other respects. - -If the required texts for either cover are too voluminous to fit -legibly, you should put the first ones listed (as many as fit -reasonably) on the actual cover, and continue the rest onto adjacent -pages. - -If you publish or distribute Opaque copies of the Document numbering -more than 100, you must either include a machine-readable Transparent -copy along with each Opaque copy, or state in or with each Opaque copy -a computer-network location from which the general network-using -public has access to download using public-standard network protocols -a complete Transparent copy of the Document, free of added material. -If you use the latter option, you must take reasonably prudent steps, -when you begin distribution of Opaque copies in quantity, to ensure -that this Transparent copy will remain thus accessible at the stated -location until at least one year after the last time you distribute an -Opaque copy (directly or through your agents or retailers) of that -edition to the public. - -It is requested, but not required, that you contact the authors of the -Document well before redistributing any large number of copies, to give -them a chance to provide you with an updated version of the Document. - -@item -MODIFICATIONS - -You may copy and distribute a Modified Version of the Document under -the conditions of sections 2 and 3 above, provided that you release -the Modified Version under precisely this License, with the Modified -Version filling the role of the Document, thus licensing distribution -and modification of the Modified Version to whoever possesses a copy -of it. In addition, you must do these things in the Modified Version: - -@enumerate A -@item -Use in the Title Page (and on the covers, if any) a title distinct -from that of the Document, and from those of previous versions -(which should, if there were any, be listed in the History section -of the Document). You may use the same title as a previous version -if the original publisher of that version gives permission. - -@item -List on the Title Page, as authors, one or more persons or entities -responsible for authorship of the modifications in the Modified -Version, together with at least five of the principal authors of the -Document (all of its principal authors, if it has fewer than five), -unless they release you from this requirement. - -@item -State on the Title page the name of the publisher of the -Modified Version, as the publisher. - -@item -Preserve all the copyright notices of the Document. - -@item -Add an appropriate copyright notice for your modifications -adjacent to the other copyright notices. - -@item -Include, immediately after the copyright notices, a license notice -giving the public permission to use the Modified Version under the -terms of this License, in the form shown in the Addendum below. - -@item -Preserve in that license notice the full lists of Invariant Sections -and required Cover Texts given in the Document's license notice. - -@item -Include an unaltered copy of this License. - -@item -Preserve the section Entitled ``History'', Preserve its Title, and add -to it an item stating at least the title, year, new authors, and -publisher of the Modified Version as given on the Title Page. If -there is no section Entitled ``History'' in the Document, create one -stating the title, year, authors, and publisher of the Document as -given on its Title Page, then add an item describing the Modified -Version as stated in the previous sentence. - -@item -Preserve the network location, if any, given in the Document for -public access to a Transparent copy of the Document, and likewise -the network locations given in the Document for previous versions -it was based on. These may be placed in the ``History'' section. -You may omit a network location for a work that was published at -least four years before the Document itself, or if the original -publisher of the version it refers to gives permission. - -@item -For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve -the Title of the section, and preserve in the section all the -substance and tone of each of the contributor acknowledgements and/or -dedications given therein. - -@item -Preserve all the Invariant Sections of the Document, -unaltered in their text and in their titles. Section numbers -or the equivalent are not considered part of the section titles. - -@item -Delete any section Entitled ``Endorsements''. Such a section -may not be included in the Modified Version. - -@item -Do not retitle any existing section to be Entitled ``Endorsements'' or -to conflict in title with any Invariant Section. - -@item -Preserve any Warranty Disclaimers. -@end enumerate - -If the Modified Version includes new front-matter sections or -appendices that qualify as Secondary Sections and contain no material -copied from the Document, you may at your option designate some or all -of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. -These titles must be distinct from any other section titles. - -You may add a section Entitled ``Endorsements'', provided it contains -nothing but endorsements of your Modified Version by various -parties---for example, statements of peer review or that the text has -been approved by an organization as the authoritative definition of a -standard. - -You may add a passage of up to five words as a Front-Cover Text, and a -passage of up to 25 words as a Back-Cover Text, to the end of the list -of Cover Texts in the Modified Version. Only one passage of -Front-Cover Text and one of Back-Cover Text may be added by (or -through arrangements made by) any one entity. If the Document already -includes a cover text for the same cover, previously added by you or -by arrangement made by the same entity you are acting on behalf of, -you may not add another; but you may replace the old one, on explicit -permission from the previous publisher that added the old one. - -The author(s) and publisher(s) of the Document do not by this License -give permission to use their names for publicity for or to assert or -imply endorsement of any Modified Version. - -@item -COMBINING DOCUMENTS - -You may combine the Document with other documents released under this -License, under the terms defined in section 4 above for modified -versions, provided that you include in the combination all of the -Invariant Sections of all of the original documents, unmodified, and -list them all as Invariant Sections of your combined work in its -license notice, and that you preserve all their Warranty Disclaimers. - -The combined work need only contain one copy of this License, and -multiple identical Invariant Sections may be replaced with a single -copy. If there are multiple Invariant Sections with the same name but -different contents, make the title of each such section unique by -adding at the end of it, in parentheses, the name of the original -author or publisher of that section if known, or else a unique number. -Make the same adjustment to the section titles in the list of -Invariant Sections in the license notice of the combined work. - -In the combination, you must combine any sections Entitled ``History'' -in the various original documents, forming one section Entitled -``History''; likewise combine any sections Entitled ``Acknowledgements'', -and any sections Entitled ``Dedications''. You must delete all -sections Entitled ``Endorsements.'' - -@item -COLLECTIONS OF DOCUMENTS - -You may make a collection consisting of the Document and other documents -released under this License, and replace the individual copies of this -License in the various documents with a single copy that is included in -the collection, provided that you follow the rules of this License for -verbatim copying of each of the documents in all other respects. - -You may extract a single document from such a collection, and distribute -it individually under this License, provided you insert a copy of this -License into the extracted document, and follow this License in all -other respects regarding verbatim copying of that document. - -@item -AGGREGATION WITH INDEPENDENT WORKS - -A compilation of the Document or its derivatives with other separate -and independent documents or works, in or on a volume of a storage or -distribution medium, is called an ``aggregate'' if the copyright -resulting from the compilation is not used to limit the legal rights -of the compilation's users beyond what the individual works permit. -When the Document is included in an aggregate, this License does not -apply to the other works in the aggregate which are not themselves -derivative works of the Document. - -If the Cover Text requirement of section 3 is applicable to these -copies of the Document, then if the Document is less than one half of -the entire aggregate, the Document's Cover Texts may be placed on -covers that bracket the Document within the aggregate, or the -electronic equivalent of covers if the Document is in electronic form. -Otherwise they must appear on printed covers that bracket the whole -aggregate. - -@item -TRANSLATION - -Translation is considered a kind of modification, so you may -distribute translations of the Document under the terms of section 4. -Replacing Invariant Sections with translations requires special -permission from their copyright holders, but you may include -translations of some or all Invariant Sections in addition to the -original versions of these Invariant Sections. You may include a -translation of this License, and all the license notices in the -Document, and any Warranty Disclaimers, provided that you also include -the original English version of this License and the original versions -of those notices and disclaimers. In case of a disagreement between -the translation and the original version of this License or a notice -or disclaimer, the original version will prevail. - -If a section in the Document is Entitled ``Acknowledgements'', -``Dedications'', or ``History'', the requirement (section 4) to Preserve -its Title (section 1) will typically require changing the actual -title. - -@item -TERMINATION - -You may not copy, modify, sublicense, or distribute the Document except -as expressly provided for under this License. Any other attempt to -copy, modify, sublicense or distribute the Document is void, and will -automatically terminate your rights under this License. However, -parties who have received copies, or rights, from you under this -License will not have their licenses terminated so long as such -parties remain in full compliance. - -@item -FUTURE REVISIONS OF THIS LICENSE - -The Free Software Foundation may publish new, revised versions -of the GNU Free Documentation 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. See -@uref{http://www.gnu.org/copyleft/}. - -Each version of the License is given a distinguishing version number. -If the Document specifies that a particular numbered version of this -License ``or any later version'' applies to it, you have the option of -following the terms and conditions either of that specified version or -of any later version that has been published (not as a draft) by the -Free Software Foundation. If the Document does not specify a version -number of this License, you may choose any version ever published (not -as a draft) by the Free Software Foundation. -@end enumerate - -@page -@heading ADDENDUM: How to use this License for your documents - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and -license notices just after the title page: - -@smallexample -@group - Copyright (C) @var{year} @var{your name}. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.2 - 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 group -@end smallexample - -If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, -replace the ``with...Texts.'' line with this: - -@smallexample -@group - with the Invariant Sections being @var{list their titles}, with - the Front-Cover Texts being @var{list}, and with the Back-Cover Texts - being @var{list}. -@end group -@end smallexample - -If you have Invariant Sections without Cover Texts, or some other -combination of the three, merge those two alternatives to suit the -situation. - -If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of -free software license, such as the GNU General Public License, -to permit their use in free software. - -@c Local Variables: -@c ispell-local-pdict: "ispell-dict" -@c End: - diff --git a/src/bin/m4/doc/gendocs_template b/src/bin/m4/doc/gendocs_template deleted file mode 100755 index 71fc286c96..0000000000 --- a/src/bin/m4/doc/gendocs_template +++ /dev/null @@ -1,91 +0,0 @@ - - - - - -%%TITLE%% - GNU Project - Free Software Foundation (FSF) - - - - - - - - - - - - - -

%%TITLE%%

- -
Free Software Foundation
-
last updated %%DATE%%
-

- -  [image of the head of a GNU] - -

-
- -

This manual (%%PACKAGE%%) is available in the following formats:

- - - -

(This page generated by the %%SCRIPTNAME%% -script.)

- - - - - diff --git a/src/bin/m4/doc/m4.1 b/src/bin/m4/doc/m4.1 deleted file mode 100644 index 66e175f36b..0000000000 --- a/src/bin/m4/doc/m4.1 +++ /dev/null @@ -1,136 +0,0 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.35. -.TH M4 "1" "November 2006" "FSF" "User Commands" -.SH NAME -M4 \- macro processor -.SH SYNOPSIS -.B m4 -[\fIOPTION\fR]... [\fIFILE\fR]... -.SH DESCRIPTION -Process macros in FILEs. If no FILE or if FILE is `\-', standard input -is read. -.PP -Mandatory or optional arguments to long options are mandatory or optional -for short options too. -.SS "Operation modes:" -.TP -\fB\-\-help\fR -display this help and exit -.TP -\fB\-\-version\fR -output version information and exit -.TP -\fB\-E\fR, \fB\-\-fatal\-warnings\fR -stop execution after first warning -.TP -\fB\-i\fR, \fB\-\-interactive\fR -unbuffer output, ignore interrupts -.TP -\fB\-P\fR, \fB\-\-prefix\-builtins\fR -force a `m4_' prefix to all builtins -.TP -\fB\-Q\fR, \fB\-\-quiet\fR, \fB\-\-silent\fR -suppress some warnings for builtins -.SS "Preprocessor features:" -.TP -\fB\-D\fR, \fB\-\-define=NAME\fR[=\fIVALUE\fR] -define NAME as having VALUE, or empty -.TP -\fB\-I\fR, \fB\-\-include\fR=\fIDIRECTORY\fR -append DIRECTORY to include path -.TP -\fB\-s\fR, \fB\-\-synclines\fR -generate `#line NUM "FILE"' lines -.TP -\fB\-U\fR, \fB\-\-undefine\fR=\fINAME\fR -undefine NAME -.SS "Limits control:" -.TP -\fB\-G\fR, \fB\-\-traditional\fR -suppress all GNU extensions -.TP -\fB\-H\fR, \fB\-\-hashsize\fR=\fIPRIME\fR -set symbol lookup hash table size [509] -.TP -\fB\-L\fR, \fB\-\-nesting\-limit\fR=\fINUMBER\fR -change artificial nesting limit [1024] -.SS "Frozen state files:" -.TP -\fB\-F\fR, \fB\-\-freeze\-state\fR=\fIFILE\fR -produce a frozen state on FILE at end -.TP -\fB\-R\fR, \fB\-\-reload\-state\fR=\fIFILE\fR -reload a frozen state from FILE at start -.SS "Debugging:" -.TP -\fB\-d\fR, \fB\-\-debug\fR[=\fIFLAGS\fR] -set debug level (no FLAGS implies `aeq') -.TP -\fB\-\-debugfile\fR=\fIFILE\fR -redirect debug and trace output -.TP -\fB\-l\fR, \fB\-\-arglength\fR=\fINUM\fR -restrict macro tracing size -.TP -\fB\-t\fR, \fB\-\-trace\fR=\fINAME\fR -trace NAME when it is defined -.SS "FLAGS is any of:" -.TP -a -show actual arguments -.TP -c -show before collect, after collect and after call -.TP -e -show expansion -.TP -f -say current input file name -.TP -i -show changes in input files -.TP -l -say current input line number -.TP -p -show results of path searches -.TP -q -quote values as necessary, with a or e flag -.TP -t -trace for all macro calls, not only traceon'ed -.TP -x -add a unique macro call id, useful with c flag -.TP -V -shorthand for all of the above flags -.PP -If defined, the environment variable `M4PATH' is a colon\-separated list -of directories included after any specified by `\-I'. -.PP -Exit status is 0 for success, 1 for failure, 63 for frozen file version -mismatch, or whatever value was passed to the m4exit macro. -.SH AUTHOR -Written by Rene' Seindal. -.SH "REPORTING BUGS" -Report bugs to . -.SH COPYRIGHT -Copyright \(co 2006 Free Software Foundation, Inc. -.br -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -.SH "SEE ALSO" -The full documentation for -.B M4 -is maintained as a Texinfo manual. If the -.B info -and -.B M4 -programs are properly installed at your site, the command -.IP -.B info m4 -.PP -should give you access to the complete manual. diff --git a/src/bin/m4/doc/m4.info b/src/bin/m4/doc/m4.info deleted file mode 100644 index 051ca7b79a..0000000000 --- a/src/bin/m4/doc/m4.info +++ /dev/null @@ -1,6116 +0,0 @@ -This is m4.info, produced by makeinfo version 4.8 from m4.texinfo. - - This manual is for GNU M4 (version 1.4.8, 20 November 2006), a -package containing an implementation of the m4 macro language. - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006 -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.2 or any later version published by the Free Software - Foundation; with no Invariant Sections, no Front-Cover Texts, and - no Back-Cover Texts. A copy of the license is included in the - section entitled "GNU Free Documentation License." - -INFO-DIR-SECTION GNU programming tools -START-INFO-DIR-ENTRY -* M4: (m4). A powerful macro processor. -END-INFO-DIR-ENTRY - - -File: m4.info, Node: Top, Next: Preliminaries, Up: (dir) - -GNU M4 -****** - -This manual is for GNU M4 (version 1.4.8, 20 November 2006), a package -containing an implementation of the m4 macro language. - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006 -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.2 or any later version published by the Free Software - Foundation; with no Invariant Sections, no Front-Cover Texts, and - no Back-Cover Texts. A copy of the license is included in the - section entitled "GNU Free Documentation License." - - GNU `m4' is an implementation of the traditional UNIX macro -processor. It is mostly SVR4 compatible, although it has some -extensions (for example, handling more than 9 positional parameters to -macros). `m4' also has builtin functions for including files, running -shell commands, doing arithmetic, etc. Autoconf needs GNU `m4' for -generating `configure' scripts, but not for running them. - - GNU `m4' was originally written by Rene' Seindal, with subsequent -changes by Franc,ois Pinard and other volunteers on the Internet. All -names and email addresses can be found in the files `m4-1.4.8/AUTHORS' -and `m4-1.4.8/THANKS' from the GNU M4 distribution. - - This is release 1.4.8. It is now considered stable: future -releases in the 1.4.x series are only meant to fix bugs, increase speed, -or improve documentation. However... - - An experimental feature, which would improve `m4' usefulness, allows -for changing the syntax for what is a "word" in `m4'. You should use: - ./configure --enable-changeword - if you want this feature compiled in. The current implementation -slows down `m4' considerably and is hardly acceptable. In the future, -`m4' 2.0 will come with a different set of new features that provide -similar capabilities, but without the inefficiencies, so changeword -will go away and _you should not count on it_. - -* Menu: - -* Preliminaries:: Introduction and preliminaries -* Invoking m4:: Invoking `m4' -* Syntax:: Lexical and syntactic conventions - -* Macros:: How to invoke macros -* Definitions:: How to define new macros -* Conditionals:: Conditionals, loops, and recursion - -* Debugging:: How to debug macros and input - -* Input Control:: Input control -* File Inclusion:: File inclusion -* Diversions:: Diverting and undiverting output - -* Text handling:: Macros for text handling -* Arithmetic:: Macros for doing arithmetic -* Shell commands:: Macros for running shell commands -* Miscellaneous:: Miscellaneous builtin macros -* Frozen files:: Fast loading of frozen state - -* Compatibility:: Compatibility with other versions of `m4' -* Answers:: Correct version of some examples -* Copying This Manual:: How to make copies of this manual -* Indices:: Indices of concepts and macros - - --- The Detailed Node Listing --- - -Introduction and preliminaries - -* Intro:: Introduction to `m4' -* History:: Historical references -* Bugs:: Problems and bugs -* Manual:: Using this manual - -Invoking `m4' - -* Operation modes:: Command line options for operation modes -* Preprocessor features:: Command line options for preprocessor features -* Limits control:: Command line options for limits control -* Frozen state:: Command line options for frozen state -* Debugging options:: Command line options for debugging -* Command line files:: Specifying input files on the command line - -Lexical and syntactic conventions - -* Names:: Macro names -* Quoted strings:: Quoting input to `m4' -* Comments:: Comments in `m4' input -* Other tokens:: Other kinds of input tokens -* Input processing:: How `m4' copies input to output - -How to invoke macros - -* Invocation:: Macro invocation -* Inhibiting Invocation:: Preventing macro invocation -* Macro Arguments:: Macro arguments -* Quoting Arguments:: On Quoting Arguments to macros -* Macro expansion:: Expanding macros - -How to define new macros - -* Define:: Defining a new macro -* Arguments:: Arguments to macros -* Pseudo Arguments:: Special arguments to macros -* Undefine:: Deleting a macro -* Defn:: Renaming macros -* Pushdef:: Temporarily redefining macros - -* Indir:: Indirect call of macros -* Builtin:: Indirect call of builtins - -Conditionals, loops, and recursion - -* Ifdef:: Testing if a macro is defined -* Ifelse:: If-else construct, or multibranch -* Shift:: Recursion in `m4' -* Forloop:: Iteration by counting -* Foreach:: Iteration by list contents - -How to debug macros and input - -* Dumpdef:: Displaying macro definitions -* Trace:: Tracing macro calls -* Debug Levels:: Controlling debugging output -* Debug Output:: Saving debugging output - -Input control - -* Dnl:: Deleting whitespace in input -* Changequote:: Changing the quote characters -* Changecom:: Changing the comment delimiters -* Changeword:: Changing the lexical structure of words -* M4wrap:: Saving text until end of input - -File inclusion - -* Include:: Including named files -* Search Path:: Searching for include files - -Diverting and undiverting output - -* Divert:: Diverting output -* Undivert:: Undiverting output -* Divnum:: Diversion numbers -* Cleardivert:: Discarding diverted text - -Macros for text handling - -* Len:: Calculating length of strings -* Index macro:: Searching for substrings -* Regexp:: Searching for regular expressions -* Substr:: Extracting substrings -* Translit:: Translating characters -* Patsubst:: Substituting text by regular expression -* Format:: Formatting strings (printf-like) - -Macros for doing arithmetic - -* Incr:: Decrement and increment operators -* Eval:: Evaluating integer expressions - -Macros for running shell commands - -* Platform macros:: Determining the platform -* Syscmd:: Executing simple commands -* Esyscmd:: Reading the output of commands -* Sysval:: Exit status -* Mkstemp:: Making temporary files - -Miscellaneous builtin macros - -* Errprint:: Printing error messages -* Location:: Printing current location -* M4exit:: Exiting from `m4' - -Fast loading of frozen state - -* Using frozen files:: Using frozen files -* Frozen file format:: Frozen file format - -Compatibility with other versions of `m4' - -* Extensions:: Extensions in GNU M4 -* Incompatibilities:: Facilities in System V m4 not in GNU M4 -* Other Incompatibilities:: Other incompatibilities - -Correct version of some examples - -* Improved exch:: Solution for `exch' -* Improved forloop:: Solution for `forloop' -* Improved foreach:: Solution for `foreach' -* Improved cleardivert:: Solution for `cleardivert' -* Improved fatal_error:: Solution for `fatal_error' - -How to make copies of this manual - -* GNU Free Documentation License:: License for copying this manual - -Indices of concepts and macros - -* Concept index:: Index for many concepts -* Macro index:: Index for all `m4' macros - - -File: m4.info, Node: Preliminaries, Next: Invoking m4, Prev: Top, Up: Top - -1 Introduction and preliminaries -******************************** - -This first chapter explains what GNU `m4' is, where `m4' comes from, -how to read and use this documentation, how to call the `m4' program, -and how to report bugs about it. It concludes by giving tips for -reading the remainder of the manual. - - The following chapters then detail all the features of the `m4' -language. - -* Menu: - -* Intro:: Introduction to `m4' -* History:: Historical references -* Bugs:: Problems and bugs -* Manual:: Using this manual - - -File: m4.info, Node: Intro, Next: History, Up: Preliminaries - -1.1 Introduction to `m4' -======================== - -`m4' is a macro processor, in the sense that it copies its input to the -output, expanding macros as it goes. Macros are either builtin or -user-defined, and can take any number of arguments. Besides just doing -macro expansion, `m4' has builtin functions for including named files, -running shell commands, doing integer arithmetic, manipulating text in -various ways, performing recursion, etc.... `m4' can be used either as -a front-end to a compiler, or as a macro processor in its own right. - - The `m4' macro processor is widely available on all UNIXes, and has -been standardized by POSIX. Usually, only a small percentage of users -are aware of its existence. However, those who find it often become -committed users. The popularity of GNU Autoconf, which requires GNU -`m4' for _generating_ `configure' scripts, is an incentive for many to -install it, while these people will not themselves program in `m4'. -GNU `m4' is mostly compatible with the System V, Release 3 version, -except for some minor differences. *Note Compatibility::, for more -details. - - Some people find `m4' to be fairly addictive. They first use `m4' -for simple problems, then take bigger and bigger challenges, learning -how to write complex sets of `m4' macros along the way. Once really -addicted, users pursue writing of sophisticated `m4' applications even -to solve simple problems, devoting more time debugging their `m4' -scripts than doing real work. Beware that `m4' may be dangerous for -the health of compulsive programmers. - - -File: m4.info, Node: History, Next: Bugs, Prev: Intro, Up: Preliminaries - -1.2 Historical references -========================= - -`GPM' was an important ancestor of `m4'. See C. Stratchey: "A General -Purpose Macro generator", Computer Journal 8,3 (1965), pp. 225 ff. -`GPM' is also succinctly described into David Gries classic "Compiler -Construction for Digital Computers". - - The classic B. Kernighan and P.J. Plauger: "Software Tools", -Addison-Wesley, Inc. (1976) describes and implements a Unix -macro-processor language, which inspired Dennis Ritchie to write `m3', -a macro processor for the AP-3 minicomputer. - - Kernighan and Ritchie then joined forces to develop the original -`m4', as described in "The M4 Macro Processor", Bell Laboratories -(1977). It had only 21 builtin macros. - - While `GPM' was more _pure_, `m4' is meant to deal with the true -intricacies of real life: macros can be recognized without being -pre-announced, skipping whitespace or end-of-lines is easier, more -constructs are builtin instead of derived, etc. - - Originally, the Kernighan and Plauger macro-processor, and then -`m3', formed the engine for the Rational FORTRAN preprocessor, that is, -the `Ratfor' equivalent of `cpp'. Later, `m4' was used as a frontend -for `Ratfor', `C' and `Cobol'. - - Rene' Seindal released his implementation of `m4', GNU `m4', in -1990, with the aim of removing the artificial limitations in many of -the traditional `m4' implementations, such as maximum line length, -macro size, or number of macros. - - The late Professor A. Dain Samples described and implemented a -further evolution in the form of `M5': "User's Guide to the M5 Macro -Language: 2nd edition", Electronic Announcement on comp.compilers -newsgroup (1992). - - Franc,ois Pinard took over maintenance of GNU `m4' in 1992, until -1994 when he released GNU `m4' 1.4, which was the stable release for 10 -years. It was at this time that GNU Autoconf decided to require GNU -`m4' as its underlying engine, since all other implementations of `m4' -had too many limitations. - - More recently, in 2004, Paul Eggert released 1.4.1 and 1.4.2 which -addressed some long standing bugs in the venerable 1.4 release. Then -in 2005 Gary V. Vaughan collected together the many patches to GNU `m4' -1.4 that were floating around the net and released 1.4.3 and 1.4.4. -And in 2006, Eric Blake joined the team and prepared patches for the -release of 1.4.5, 1.4.6, 1.4.7, and 1.4.8. - - Meanwhile, development has continued on new features for `m4', such -as dynamic module loading and additional builtins. When complete, GNU -`m4' 2.0 will start a new series of releases. - - -File: m4.info, Node: Bugs, Next: Manual, Prev: History, Up: Preliminaries - -1.3 Problems and bugs -===================== - -If you have problems with GNU M4 or think you've found a bug, please -report it. Before reporting a bug, make sure you've actually found a -real bug. Carefully reread the documentation and see if it really says -you can do what you're trying to do. If it's not clear whether you -should be able to do something or not, report that too; it's a bug in -the documentation! - - Before reporting a bug or trying to fix it yourself, try to isolate -it to the smallest possible input file that reproduces the problem. -Then send us the input file and the exact results `m4' gave you. Also -say what you expected to occur; this will help us decide whether the -problem was really in the documentation. - - Once you've got a precise problem, send e-mail to (Internet) -. Please include the version number of `m4' you are -using. You can get this information with the command `m4 --version'. -Also provide details about the platform you are executing on. - - Non-bug suggestions are always welcome as well. If you have -questions about things that are unclear in the documentation or are -just obscure features, please report them too. - - -File: m4.info, Node: Manual, Prev: Bugs, Up: Preliminaries - -1.4 Using this manual -===================== - -This manual contains a number of examples of `m4' input and output, and -a simple notation is used to distinguish input, output and error -messages from `m4'. Examples are set out from the normal text, and -shown in a fixed width font, like this - - This is an example of an example! - - To distinguish input from output, all output from `m4' is prefixed -by the string `=>', and all error messages by the string `error-->'. -Thus - - Example of input line - =>Output line from m4 - error-->and an error message - - The sequence `^D' in an example indicates the end of the input file. -The majority of these examples are self-contained, and you can run them -with similar results by invoking `m4 -d'. In fact, the testsuite that -is bundled in the GNU M4 package consists of the examples in this -document! - - As each of the predefined macros in `m4' is described, a prototype -call of the macro will be shown, giving descriptive names to the -arguments, e.g., - - -- Composite: example (STRING, [COUNT = `1'], [ARGUMENT]...) - This is a sample prototype. There is not really a macro named - `example', but this documents that if there were, it would be a - Composite macro, rather than a Builtin. It requires at least one - argument, STRING. Remember that in `m4', there must not be a - space between the macro name and the opening parenthesis, unless - it was intended to call the macro without any arguments. The - brackets around COUNT and ARGUMENT show that these arguments are - optional. If COUNT is omitted, the macro behaves as if count were - `1', whereas if ARGUMENT is omitted, the macro behaves as if it - were the empty string. A blank argument is not the same as an - omitted argument. For example, `example(`a')', `example(`a',`1')', - and `example(`a',`1',)' would behave identically with COUNT set to - `1'; while `example(`a',)' and `example(`a',`')' would explicitly - pass the empty string for COUNT. The ellipses (`...') show that - the macro processes additional arguments after ARGUMENT, rather - than ignoring them. - - All macro arguments in `m4' are strings, but some are given special -interpretation, e.g., as numbers, file names, regular expressions, etc. -The documentation for each macro will state how the parameters are -interpreted, and what happens if the argument cannot be parsed -according to the desired interpretation. Unless specified otherwise, a -parameter specified to be a number is parsed as a decimal, even if the -argument has leading zeros; and parsing the empty string as a number -results in 0 rather than an error, although a warning will be issued. - - This document consistently writes and uses "builtin", without a -hyphen, as if it were an English word. This is how the `builtin' -primitive is spelled within `m4'. - - -File: m4.info, Node: Invoking m4, Next: Syntax, Prev: Preliminaries, Up: Top - -2 Invoking `m4' -*************** - -The format of the `m4' command is: - - `m4' [OPTION...] [FILE...] - - All options begin with `-', or if long option names are used, with -`--'. A long option name need not be written completely, any -unambiguous prefix is sufficient. POSIX requires `m4' to recognize -arguments intermixed with files, even when `POSIXLY_CORRECT' is set in -the environment. Most options take effect at startup regardless of -their position, but some are documented below as taking effect after -any files that occurred earlier in the command line. The argument `--' -is a marker to denote the end of options. - - With short options, options that do not take arguments may be -combined into a single command line argument with subsequent options, -options with mandatory arguments may be provided either as a single -command line argument or as two arguments, and options with optional -arguments must be provided as a single argument. In other words, `m4 --QPDfoo -d a -d+f' is equivalent to `m4 -Q -P -D foo -d -d+f -- ./a', -although the latter form is considered canonical. - - With long options, options with mandatory arguments may be provided -with an equal sign (`=') in a single argument, or as two arguments, and -options with optional arguments must be provided as a single argument. -In other words, `m4 --def foo --debug a' is equivalent to `m4 ---define=foo --debug= -- ./a', although the latter form is considered -canonical (not to mention more robust, in case a future version of `m4' -introduces an option named `--default'). - - `m4' understands the following options, grouped by functionality. - -* Menu: - -* Operation modes:: Command line options for operation modes -* Preprocessor features:: Command line options for preprocessor features -* Limits control:: Command line options for limits control -* Frozen state:: Command line options for frozen state -* Debugging options:: Command line options for debugging -* Command line files:: Specifying input files on the command line - - -File: m4.info, Node: Operation modes, Next: Preprocessor features, Up: Invoking m4 - -2.1 Command line options for operation modes -============================================ - -Several options control the overall operation of `m4': - -`--help' - Print a help summary on standard output, then immediately exit - `m4' without reading any input files or performing any other - actions. - -`--version' - Print the version number of the program on standard output, then - immediately exit `m4' without reading any input files or - performing any other actions. - -`-E' -`--fatal-warnings' - Stop execution and exit `m4' once the first warning has been - issued, considering all of them to be fatal. - -`-i' -`--interactive' -`-e' - Makes this invocation of `m4' interactive. This means that all - output will be unbuffered, and interrupts will be ignored. The - spelling `-e' exists for compatibility with other `m4' - implementations, and issues a warning because it may be withdrawn - in a future version of GNU M4. - -`-P' -`--prefix-builtins' - Internally modify _all_ builtin macro names so they all start with - the prefix `m4_'. For example, using this option, one should write - `m4_define' instead of `define', and `m4___file__' instead of - `__file__'. This option has no effect if `-R' is also specified. - -`-Q' -`--quiet' -`--silent' - Suppress warnings, such as missing or superfluous arguments in - macro calls, or treating the empty string as zero. - -`-W REGEXP' -`--word-regexp=REGEXP' - Use REGEXP as an alternative syntax for macro names. This - experimental option will not be present in all GNU `m4' - implementations (*note Changeword::). - - -File: m4.info, Node: Preprocessor features, Next: Limits control, Prev: Operation modes, Up: Invoking m4 - -2.2 Command line options for preprocessor features -================================================== - -Several options allow `m4' to behave more like a preprocessor. Macro -definitions and deletions can be made on the command line, the search -path can be altered, and the output file can track where the input came -from. These features occur with the following options: - -`-D NAME[=VALUE]' -`--define=NAME[=VALUE]' - This enters NAME into the symbol table, before any input files are - read. If `=VALUE' is missing, the value is taken to be the empty - string. The VALUE can be any string, and the macro can be defined - to take arguments, just as if it was defined from within the - input. This option may be given more than once; order with - respect to file names is significant, and redefining the same NAME - loses the previous value. - -`-I DIRECTORY' -`--include=DIRECTORY' - Make `m4' search DIRECTORY for included files that are not found - in the current working directory. *Note Search Path::, for more - details. This option may be given more than once. - -`-s' -`--synclines' - Generate synchronization lines, for use by the C preprocessor or - other similar tools. Order is significant with respect to file - names. This option is useful, for example, when `m4' is used as a - front end to a compiler. Source file name and line number - information is conveyed by directives of the form `#line LINENUM - "FILE"', which are inserted as needed into the middle of the - output. Such directives mean that the following line originated - or was expanded from the contents of input file FILE at line - LINENUM. The `"FILE"' part is often omitted when the file name - did not change from the previous directive. - - Synchronization directives are always given on complete lines by - themselves. When a synchronization discrepancy occurs in the - middle of an output line, the associated synchronization directive - is delayed until the beginning of the next generated line. - -`-U NAME' -`--undefine=NAME' - This deletes any predefined meaning NAME might have. Obviously, - only predefined macros can be deleted in this way. This option - may be given more than once; undefining a NAME that does not have a - definition is silently ignored. Order is significant with respect - to file names. - - -File: m4.info, Node: Limits control, Next: Frozen state, Prev: Preprocessor features, Up: Invoking m4 - -2.3 Command line options for limits control -=========================================== - -There are some limits within `m4' that can be tuned. For -compatibility, `m4' also accepts some options that control limits in -other implementations, but which are automatically unbounded (limited -only by your hardware and operating system constraints) in GNU `m4'. - -`-G' -`--traditional' - Suppress all the extensions made in this implementation, compared - to the System V version. *Note Compatibility::, for a list of - these. - -`-H NUM' -`--hashsize=NUM' - Make the internal hash table for symbol lookup be NUM entries big. - For better performance, the number should be prime, but this is not - checked. The default is 509 entries. It should not be necessary - to increase this value, unless you define an excessive number of - macros. - -`-L NUM' -`--nesting-limit=NUM' - Artificially limit the nesting of macro calls to NUM levels, - stopping program execution if this limit is ever exceeded. When - not specified, nesting is limited to 1024 levels. A value of zero - means unlimited; but then heavily nested code could potentially - cause a stack overflow. - - The precise effect of this option might be more correctly - associated with textual nesting than dynamic recursion. It has - been useful when some complex `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. - - This option does _not_ have the ability to break endless - rescanning loops, since these do not necessarily consume much - memory or stack space. Through clever usage of rescanning loops, - one can request complex, time-consuming computations from `m4' - with useful results. Putting limitations in this area would break - `m4' power. There are many pathological cases: - `define(`a', `a')a' is only the simplest example (but *note - Compatibility::). Expecting GNU `m4' to detect these would be a - little like expecting a compiler system to detect and diagnose - endless loops: it is a quite _hard_ problem in general, if not - undecidable! - -`-B NUM' -`-S NUM' -`-T NUM' - These options are present for compatibility with System V `m4', but - do nothing in this implementation. They may disappear in future - releases, and issue a warning to that effect. - -`-N NUM' -`--diversions=NUM' - These options are present only for compatibility with previous - versions of GNU `m4', and were controlling the number of possible - diversions which could be used at the same time. They do nothing, - because there is no fixed limit anymore. They may disappear in - future releases, and issue a warning to that effect. - - -File: m4.info, Node: Frozen state, Next: Debugging options, Prev: Limits control, Up: Invoking m4 - -2.4 Command line options for frozen state -========================================= - -GNU `m4' comes with a feature of freezing internal state (*note Frozen -files::). This can be used to speed up `m4' execution when reusing a -common initialization script. - -`-F FILE' -`--freeze-state=FILE' - Once execution is finished, write out the frozen state on the - specified FILE. It is conventional, but not required, for FILE to - end in `.m4f'. - -`-R FILE' -`--reload-state=FILE' - Before execution starts, recover the internal state from the - specified frozen FILE. The options `-D', `-U', and `-t' take - effect after state is reloaded, but before the input files are - read. - - -File: m4.info, Node: Debugging options, Next: Command line files, Prev: Frozen state, Up: Invoking m4 - -2.5 Command line options for debugging -====================================== - -Finally, there are several options for aiding in debugging `m4' scripts. - -`-d[FLAGS]' -`--debug[=FLAGS]' - Set the debug-level according to the flags FLAGS. The debug-level - controls the format and amount of information presented by the - debugging functions. *Note Debug Levels::, for more details on - the format and meaning of FLAGS. If omitted, FLAGS defaults to - `aeq'. - -`--debugfile=FILE' -`-o FILE' -`--error-output=FILE' - Redirect `dumpdef' output, debug messages, and trace output to the - named FILE. Warnings, error messages, and `errprint' output are - still printed to standard error. If unspecified, debug output goes - to standard error; if empty, debug output is discarded. *Note - Debug Output::, for more details. The spellings `-o' and - `--error-output' are misleading and inconsistent with other GNU - tools; for now they are silently accepted as synonyms of - `--debugfile', but in a future version of M4, using them will - cause a warning to be issued. - -`-l NUM' -`--arglength=NUM' - Restrict the size of the output generated by macro tracing to NUM - characters per trace line. If unspecified or zero, output is - unlimited. *Note Debug Levels::, for more details. - -`-t NAME' -`--trace=NAME' - This enables tracing for the macro NAME, at any point where it is - defined. NAME need not be defined when this option is given. - This option may be given more than once, and order is significant - with respect to file names. *Note Trace::, for more details. - - -File: m4.info, Node: Command line files, Prev: Debugging options, Up: Invoking m4 - -2.6 Specifying input files on the command line -============================================== - -The remaining arguments on the command line are taken to be input file -names. If no names are present, standard input is read. A file name -of `-' is taken to mean standard input. It is conventional, but not -required, for input files to end in `.m4'. - - The input files are read in the sequence given. Standard input can -be read more than once, so the file name `-' may appear multiple times -on the command line; this makes a difference when input is from a -terminal or other special file type. It is an error if an input file -ends in the middle of argument collection, a comment, or a quoted -string. - - The options `--define' (`-D'), `--undefine' (`-U'), `--synclines' -(`-s'), and `--trace' (`-t') only take effect after processing input -from any file names that occur earlier on the command line. - - If none of the input files invoked `m4exit' (*note M4exit::), the -exit status of `m4' will be 0 for success, 1 for general failure (such -as problems with reading an input file), and 63 for version mismatch -(*note Using frozen files::). - - If you need to read a file whose name starts with a `-', you can -specify it as `./-file', or use `--' to mark the end of options. - - -File: m4.info, Node: Syntax, Next: Macros, Prev: Invoking m4, Up: Top - -3 Lexical and syntactic conventions -*********************************** - -As `m4' reads its input, it separates it into "tokens". A token is -either a name, a quoted string, or any single character, that is not a -part of either a name or a string. Input to `m4' can also contain -comments. GNU `m4' does not yet understand locales; all operations are -byte-oriented rather than character-oriented. However, `m4' is -eight-bit clean, so you can use non-ASCII characters in quoted strings -(*note Changequote::), comments (*note Changecom::), and macro names -(*note Indir::), with the exception of the NUL character (the zero byte -`'\0''). - -* Menu: - -* Names:: Macro names -* Quoted strings:: Quoting input to `m4' -* Comments:: Comments in `m4' input -* Other tokens:: Other kinds of input tokens -* Input processing:: How `m4' copies input to output - - -File: m4.info, Node: Names, Next: Quoted strings, Up: Syntax - -3.1 Macro names -=============== - -A name is any sequence of letters, digits, and the character `_' -(underscore), where the first character is not a digit. `m4' will use -the longest such sequence found in the input. If a name has a macro -definition, it will be subject to macro expansion (*note Macros::). -Names are case-sensitive. - - Examples of legal names are: `foo', `_tmp', and `name01'. - - -File: m4.info, Node: Quoted strings, Next: Comments, Prev: Names, Up: Syntax - -3.2 Quoting input to `m4' -========================= - -A quoted string is a sequence of characters surrounded by quote -strings, defaulting to ``' and `'', where the nested begin and end -quotes within the string are balanced. The value of a string token is -the text, with one level of quotes stripped off. Thus - - `' - => - -is the empty string, and double-quoting turns into single-quoting. - - ``quoted'' - =>`quoted' - - The quote characters can be changed at any time, using the builtin -macro `changequote'. *Note Changequote::, for more information. - - -File: m4.info, Node: Comments, Next: Other tokens, Prev: Quoted strings, Up: Syntax - -3.3 Comments in `m4' input -========================== - -Comments in `m4' are normally delimited by the characters `#' and -newline. All characters between the comment delimiters are ignored, -but the entire comment (including the delimiters) is passed through to -the output--comments are _not_ discarded by `m4'. - - Comments cannot be nested, so the first newline after a `#' ends the -comment. The commenting effect of the begin-comment string can be -inhibited by quoting it. - - `quoted text' # `commented text' - =>quoted text # `commented text' - `quoting inhibits' `#' `comments' - =>quoting inhibits # comments - - The comment delimiters can be changed to any string at any time, -using the builtin macro `changecom'. *Note Changecom::, for more -information. - - -File: m4.info, Node: Other tokens, Next: Input processing, Prev: Comments, Up: Syntax - -3.4 Other kinds of input tokens -=============================== - -Any character, that is neither a part of a name, nor of a quoted string, -nor a comment, is a token by itself. When not in the context of macro -expansion, all of these tokens are just copied to output. However, -during macro expansion, whitespace characters (space, tab, newline, -formfeed, carriage return, vertical tab), parentheses (`(' and `)'), -comma (`,'), and dollar (`$') have additional roles, explained later. - - -File: m4.info, Node: Input processing, Prev: Other tokens, Up: Syntax - -3.5 How `m4' copies input to output -=================================== - -As `m4' reads the input token by token, it will copy each token -directly to the output immediately. - - The exception is when it finds a word with a macro definition. In -that case `m4' will calculate the macro's expansion, possibly reading -more input to get the arguments. It then inserts the expansion in front -of the remaining input. In other words, the resulting text from a macro -call will be read and parsed into tokens again. - - `m4' expands a macro as soon as possible. If it finds a macro call -when collecting the arguments to another, it will expand the second -call first. For a running example, examine how `m4' handles this input: - - format(`Result is %d', eval(`2**15')) - -First, `m4' sees that the token `format' is a macro name, so it -collects the tokens `(', ``Result is %d'', `,', and ` ', before -encountering another potential macro. Sure enough, `eval' is a macro -name, so the nested argument collection picks up `(', ``2**15'', and -`)', invoking the eval macro with the lone argument of `2**15'. The -expansion of `eval(2**15)' is `32768', which is then rescanned as the -five tokens `3', `2', `7', `6', and `8'; and combined with the next -`)', the format macro now has all its arguments, as if the user had -typed: - - format(`Result is %d', 32768) - -The format macro expands to `Result is 32768', and we have another -round of scanning for the tokens `Result', ` ', `is', ` ', `3', `2', -`7', `6', and `8'. None of these are macros, so the final output is - - =>Result is 32768 - - The order in which `m4' expands the macros can be explored using the -trace facilities of GNU `m4' (*note Trace::). - - This process continues until there are no more macro calls to expand -and all the input has been consumed. - - -File: m4.info, Node: Macros, Next: Definitions, Prev: Syntax, Up: Top - -4 How to invoke macros -********************** - -This chapter covers macro invocation, macro arguments and how macro -expansion is treated. - -* Menu: - -* Invocation:: Macro invocation -* Inhibiting Invocation:: Preventing macro invocation -* Macro Arguments:: Macro arguments -* Quoting Arguments:: On Quoting Arguments to macros -* Macro expansion:: Expanding macros - - -File: m4.info, Node: Invocation, Next: Inhibiting Invocation, Up: Macros - -4.1 Macro invocation -==================== - -Macro invocations has one of the forms - - name - -which is a macro invocation without any arguments, or - - name(arg1, arg2, ..., argN) - -which is a macro invocation with N arguments. Macros can have any -number of arguments. All arguments are strings, but different macros -might interpret the arguments in different ways. - - The opening parenthesis _must_ follow the NAME directly, with no -spaces in between. If it does not, the macro is called with no -arguments at all. - - For a macro call to have no arguments, the parentheses _must_ be -left out. The macro call - - name() - -is a macro call with one argument, which is the empty string, not a call -with no arguments. - - -File: m4.info, Node: Inhibiting Invocation, Next: Macro Arguments, Prev: Invocation, Up: Macros - -4.2 Preventing macro invocation -=============================== - -An innovation of the `m4' language, compared to some of its -predecessors (like Stratchey's `GPM', for example), is the ability to -recognize macro calls without resorting to any special, prefixed -invocation character. While generally useful, this feature might -sometimes be the source of spurious, unwanted macro calls. So, GNU -`m4' offers several mechanisms or techniques for inhibiting the -recognition of names as macro calls. - - First of all, many builtin macros cannot meaningfully be called -without arguments. For any of these macros, whenever an opening -parenthesis does not immediately follow their name, the builtin macro -call is not triggered. This solves the most usual cases, like for -`include' or `eval'. Later in this document, the sentence "This macro -is recognized only with parameters" refers to this specific provision. - - There is also a command line option (`--prefix-builtins', or `-P', -*note Invoking m4: Operation modes.) that renames all builtin macros -with a prefix of `m4_' at startup. The option has no effect whatsoever -on user defined macros. For example, with this option, one has to -write `m4_dnl' and even `m4_m4exit'. It also has no effect on whether -a macro requires parameters. - - Another alternative is to redefine problematic macros to a name less -likely to cause conflicts, *Note Definitions::. - - If your version of GNU `m4' has the `changeword' feature compiled -in, it offers far more flexibility in specifying the syntax of macro -names, both builtin or user-defined. *Note Changeword::, for more -information on this experimental feature. - - Of course, the simplest way to prevent a name from being interpreted -as a call to an existing macro is to quote it. The remainder of this -section studies a little more deeply how quoting affects macro -invocation, and how quoting can be used to inhibit macro invocation. - - Even if quoting is usually done over the whole macro name, it can -also be done over only a few characters of this name (provided, of -course, that the unquoted portions are not also a macro). It is also -possible to quote the empty string, but this works only _inside_ the -name. For example: - - `divert' - =>divert - `d'ivert - =>divert - di`ver't - =>divert - div`'ert - =>divert - -all yield the string `divert'. While in both: - - `'divert - => - divert`' - => - -the `divert' builtin macro will be called, which expands to the empty -string. - - The output of macro evaluations is always rescanned. The following -example would yield the string `de', exactly as if `m4' has been given -`substr(`abcde', `3', `2')' as input: - - define(`x', `substr(ab') - => - define(`y', `cde, `3', `2')') - => - x`'y - =>de - - Unquoted strings on either side of a quoted string are subject to -being recognized as macro names. In the following example, quoting the -empty string allows for the second `macro' to be recognized as such: - - define(`macro', `m') - => - macro(`m')macro - =>mmacro - macro(`m')`'macro - =>mm - - Quoting may prevent recognizing as a macro name the concatenation of -a macro expansion with the surrounding characters. In this example: - - define(`macro', `di$1') - => - macro(`v')`ert' - =>divert - macro(`v')ert - => - -the input will produce the string `divert'. When the quotes were -removed, the `divert' builtin was called instead. - - -File: m4.info, Node: Macro Arguments, Next: Quoting Arguments, Prev: Inhibiting Invocation, Up: Macros - -4.3 Macro arguments -=================== - -When a name is seen, and it has a macro definition, it will be expanded -as a macro. - - If the name is followed by an opening parenthesis, the arguments -will be collected before the macro is called. If too few arguments are -supplied, the missing arguments are taken to be the empty string. -However, some builtins are documented to behave differently for a -missing optional argument than for an explicit empty string. If there -are too many arguments, the excess arguments are ignored. Unquoted -leading whitespace is stripped off all arguments, but whitespace -generated by a macro expansion or occuring after a macro that expanded -to an empty string remains intact. Whitespace includes space, tab, -newline, carriage return, vertical tab, and formfeed. - - define(`macro', `$1') - => - macro( unquoted leading space lost) - =>unquoted leading space lost - macro(` quoted leading space kept') - => quoted leading space kept - macro( - divert `unquoted space kept after expansion') - => unquoted space kept after expansion - macro(macro(` - ')`whitespace from expansion kept') - => - =>whitespace from expansion kept - macro(`unquoted trailing whitespace kept' - ) - =>unquoted trailing whitespace kept - => - - Normally `m4' will issue warnings if a builtin macro is called with -an inappropriate number of arguments, but it can be suppressed with the -`--quiet' command line option (or `--silent', or `-Q', *note Invoking -m4: Operation modes.). For user defined macros, there is no check of -the number of arguments given. - - Macros are expanded normally during argument collection, and whatever -commas, quotes and parentheses that might show up in the resulting -expanded text will serve to define the arguments as well. Thus, if FOO -expands to `, b, c', the macro call - - bar(a foo, d) - -is a macro call with four arguments, which are `a ', `b', `c' and `d'. -To understand why the first argument contains whitespace, remember that -unquoted leading whitespace is never part of an argument, but trailing -whitespace always is. - - It is possible for a macro's definition to change during argument -collection, in which case the expansion uses the definition that was in -effect at the time the opening `(' was seen. - - define(`f', `1') - => - f(define(`f', `2')) - =>1 - f - =>2 - - It is an error if the end of file occurs while collecting arguments. - - hello world - =>hello world - define( - ^D - error-->m4:stdin:2: ERROR: end of file in argument list - - -File: m4.info, Node: Quoting Arguments, Next: Macro expansion, Prev: Macro Arguments, Up: Macros - -4.4 On Quoting Arguments to macros -================================== - -Each argument has unquoted leading whitespace removed. Within each -argument, all unquoted parentheses must match. For example, if FOO is -a macro, - - foo(() (`(') `(') - -is a macro call, with one argument, whose value is `() (() ('. Commas -separate arguments, except when they occur inside quotes, comments, or -unquoted parentheses. *Note Pseudo Arguments::, for examples. - - It is common practice to quote all arguments to macros, unless you -are sure you want the arguments expanded. Thus, in the above example -with the parentheses, the `right' way to do it is like this: - - foo(`() (() (') - - It is, however, in certain cases necessary or convenient 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. For consistency, -this manual follows the rule of thumb that each layer of parentheses -introduces another layer of single quoting, except when showing the -consequences of quoting rules. This is done even when the quoted string -cannot be a macro, such as with integers when you have not changed the -syntax via `changeword' (*note Changeword::). - - -File: m4.info, Node: Macro expansion, Prev: Quoting Arguments, Up: Macros - -4.5 Macro expansion -=================== - -When the arguments, if any, to a macro call have been collected, the -macro is expanded, and the expansion text is pushed back onto the input -(unquoted), and reread. The expansion text from one macro call might -therefore result in more macros being called, if the calls are included, -completely or partially, in the first macro calls' expansion. - - Taking a very simple example, if FOO expands to `bar', and BAR -expands to `Hello world', the input - - foo - -will expand first to `bar', and when this is reread and expanded, into -`Hello world'. - - -File: m4.info, Node: Definitions, Next: Conditionals, Prev: Macros, Up: Top - -5 How to define new macros -************************** - -Macros can be defined, redefined and deleted in several different ways. -Also, it is possible to redefine a macro without losing a previous -value, and bring back the original value at a later time. - -* Menu: - -* Define:: Defining a new macro -* Arguments:: Arguments to macros -* Pseudo Arguments:: Special arguments to macros -* Undefine:: Deleting a macro -* Defn:: Renaming macros -* Pushdef:: Temporarily redefining macros - -* Indir:: Indirect call of macros -* Builtin:: Indirect call of builtins - - -File: m4.info, Node: Define, Next: Arguments, Up: Definitions - -5.1 Defining a macro -==================== - -The normal way to define or redefine macros is to use the builtin -`define': - - -- Builtin: define (NAME, [EXPANSION]) - Defines NAME to expand to EXPANSION. If EXPANSION is not given, - it is taken to be empty. - - The expansion of `define' is void. The macro `define' is - recognized only with parameters. - - The following example defines the macro FOO to expand to the text -`Hello World.'. - - define(`foo', `Hello world.') - => - foo - =>Hello world. - - The empty line in the output is there because the newline is not a -part of the macro definition, and it is consequently copied to the -output. This can be avoided by use of the macro `dnl'. *Note Dnl::, -for details. - - The first argument to `define' should be quoted; otherwise, if the -macro is already defined, you will be defining a different macro. This -example shows the problems with underquoting, since we did not want to -redefine `one': - - define(foo, one) - => - define(foo, two) - => - one - =>two - - GNU `m4' normally replaces only the _topmost_ definition of a macro -if it has several definitions from `pushdef' (*note Pushdef::). Some -other implementations of `m4' replace all definitions of a macro with -`define'. *Note Incompatibilities::, for more details. - - As a GNU extension, the first argument to `define' does not have to -be a simple word. It can be any text string, even the empty string. A -macro with a non-standard name cannot be invoked in the normal way, as -the name is not recognized. It can only be referenced by the builtins -`Indir' (*note Indir::) and `Defn' (*note Defn::). - - Arrays and associative arrays can be simulated by using this trick. - - define(`array', `defn(format(``array[%d]'', `$1'))') - => - define(`array_set', `define(format(``array[%d]'', `$1'), `$2')') - => - array_set(`4', `array element no. 4') - => - array_set(`17', `array element no. 17') - => - array(`4') - =>array element no. 4 - array(eval(`10 + 7')) - =>array element no. 17 - - Change the `%d' to `%s' and it is an associative array. - - -File: m4.info, Node: Arguments, Next: Pseudo Arguments, Prev: Define, Up: Definitions - -5.2 Arguments to macros -======================= - -Macros can have arguments. The Nth argument is denoted by `$n' in the -expansion text, and is replaced by the Nth actual argument, when the -macro is expanded. Replacement of arguments happens before rescanning, -regardless of how many nesting levels of quoting appear in the -expansion. Here is an example of a macro with two arguments. It -simply exchanges the order of the two arguments. - - define(`exch', `$2, $1') - => - exch(`arg1', `arg2') - =>arg2, arg1 - - This can be used, for example, if you like the arguments to `define' -to be reversed. - - define(`exch', `$2, $1') - => - define(exch(``expansion text'', ``macro'')) - => - macro - =>expansion text - - *Note Quoting Arguments::, for an explanation of the double quotes. -(You should try and improve this example so that clients of `exch' do -not have to double quote; or *note Answers: Improved exch.). - - GNU `m4' allows the number following the `$' to consist of one or -more digits, allowing macros to have any number of arguments. This is -not so in UNIX implementations of `m4', which only recognize one digit. - - As a special case, the zeroth argument, `$0', is always the name of -the macro being expanded. - - define(`test', ``Macro name: $0'') - => - test - =>Macro name: test - - If you want quoted text to appear as part of the expansion text, -remember that quotes can be nested in quoted strings. Thus, in - - define(`foo', `This is macro `foo'.') - => - foo - =>This is macro foo. - -The `foo' in the expansion text is _not_ expanded, since it is a quoted -string, and not a name. - - -File: m4.info, Node: Pseudo Arguments, Next: Undefine, Prev: Arguments, Up: Definitions - -5.3 Special arguments to macros -=============================== - -There is a special notation for the number of actual arguments supplied, -and for all the actual arguments. - - The number of actual arguments in a macro call is denoted by `$#' in -the expansion text. Thus, a macro to display the number of arguments -given can be - - define(`nargs', `$#') - => - nargs - =>0 - nargs() - =>1 - nargs(`arg1', `arg2', `arg3') - =>3 - nargs(`commas can be quoted, like this') - =>1 - nargs(arg1#inside comments, commas do not separate arguments - still arg1) - =>1 - nargs((unquoted parentheses, like this, group arguments)) - =>1 - - The notation `$*' can be used in the expansion text to denote all -the actual arguments, unquoted, with commas in between. For example - - define(`echo', `$*') - => - echo(arg1, arg2, arg3 , arg4) - =>arg1,arg2,arg3 ,arg4 - - Often each argument should be quoted, and the notation `$@' handles -that. It is just like `$*', except that it quotes each argument. A -simple example of that is: - - define(`echo', `$@') - => - echo(arg1, arg2, arg3 , arg4) - =>arg1,arg2,arg3 ,arg4 - - Where did the quotes go? Of course, they were eaten, when the -expanded text were reread by `m4'. To show the difference, try - - define(`echo1', `$*') - => - define(`echo2', `$@') - => - define(`foo', `This is macro `foo'.') - => - echo1(foo) - =>This is macro This is macro foo.. - echo1(`foo') - =>This is macro foo. - echo2(foo) - =>This is macro foo. - echo2(`foo') - =>foo - -*Note Trace::, if you do not understand this. As another example of the -difference, remember that comments encountered in arguments are passed -untouched to the macro, and that quoting disables comments. - - define(`echo1', `$*') - => - define(`echo2', `$@') - => - define(`foo', `bar') - => - echo1(#foo'foo - foo) - =>#foo'foo - =>bar - echo2(#foo'foo - foo) - =>#foobar - =>bar' - - A `$' sign in the expansion text, that is not followed by anything -`m4' understands, is simply copied to the macro expansion, as any other -text is. - - define(`foo', `$$$ hello $$$') - => - foo - =>$$$ hello $$$ - - If you want a macro to expand to something like `$12', the judicious -use of nested quoting can put a safe character between the `$' and the -next character, relying on the rescanning to remove the nested quote. -This will prevent `m4' from interpreting the `$' sign as a reference to -an argument. - - define(`foo', `no nested quote: $1') - => - foo(`arg') - =>no nested quote: arg - define(`foo', `nested quote around $: `$'1') - => - foo(`arg') - =>nested quote around $: $1 - define(`foo', `nested empty quote after $: $`'1') - => - foo(`arg') - =>nested empty quote after $: $1 - define(`foo', `nested quote around next character: $`1'') - => - foo(`arg') - =>nested quote around next character: $1 - define(`foo', `nested quote around both: `$1'') - => - foo(`arg') - =>nested quote around both: arg - - -File: m4.info, Node: Undefine, Next: Defn, Prev: Pseudo Arguments, Up: Definitions - -5.4 Deleting a macro -==================== - -A macro definition can be removed with `undefine': - - -- Builtin: undefine (NAME...) - For each argument, remove the macro NAME. The macro names must - necessarily be quoted, since they will be expanded otherwise. - - The expansion of `undefine' is void. The macro `undefine' is - recognized only with parameters. - - foo bar blah - =>foo bar blah - define(`foo', `some')define(`bar', `other')define(`blah', `text') - => - foo bar blah - =>some other text - undefine(`foo') - => - foo bar blah - =>foo other text - undefine(`bar', `blah') - => - foo bar blah - =>foo bar blah - - Undefining a macro inside that macro's expansion is safe; the macro -still expands to the definition that was in effect at the `('. - - define(`f', ``$0':$1') - => - f(f(f(undefine(`f')`hello world'))) - =>f:f:f:hello world - f(`bye') - =>f(bye) - - It is not an error for NAME to have no macro definition. In that -case, `undefine' does nothing. - - -File: m4.info, Node: Defn, Next: Pushdef, Prev: Undefine, Up: Definitions - -5.5 Renaming macros -=================== - -It is possible to rename an already defined macro. To do this, you need -the builtin `defn': - - -- Builtin: defn (NAME) - Expands to the _quoted definition_ of NAME. If the argument is - not a defined macro, the expansion is void. - - If NAME is a user-defined macro, the quoted definition is simply - the quoted expansion text. If, instead, NAME is a builtin, the - expansion is a special token, which points to the builtin's - internal definition. This token is only meaningful as the second - argument to `define' (and `pushdef'), and is silently converted to - an empty string in most other contexts. - - The macro `defn' is recognized only with parameters. - - Its normal use is best understood through an example, which shows -how to rename `undefine' to `zap': - - define(`zap', defn(`undefine')) - => - zap(`undefine') - => - undefine(`zap') - =>undefine(zap) - - In this way, `defn' can be used to copy macro definitions, and also -definitions of builtin macros. Even if the original macro is removed, -the other name can still be used to access the definition. - - The fact that macro definitions can be transferred also explains why -you should use `$0', rather than retyping a macro's name in its -definition: - - define(`foo', `This is `$0'') - => - define(`bar', defn(`foo')) - => - bar - =>This is bar - - Macros used as string variables should be referred through `defn', -to avoid unwanted expansion of the text: - - define(`string', `The macro dnl is very useful - ') - => - string - =>The macro - defn(`string') - =>The macro dnl is very useful - => - - However, it is important to remember that `m4' rescanning is purely -textual. If an unbalanced end-quote string occurs in a macro -definition, the rescan will see that embedded quote as the termination -of the quoted string, and the remainder of the macro's definition will -be rescanned unquoted. Thus it is a good idea to avoid unbalanced -end-quotes in macro definitions or arguments to macros. - - define(`foo', a'a) - => - define(`a', `A') - => - define(`echo', `$@') - => - foo - =>A'A - defn(`foo') - =>aA' - echo(foo) - =>AA' - - Using `defn' to generate special tokens for builtin macros outside -of expected contexts can sometimes trigger warnings. But most of the -time, such tokens are silently converted to the empty string. - - defn(`defn') - => - define(defn(`divnum'), `cannot redefine a builtin token') - error-->m4:stdin:2: Warning: define: invalid macro name ignored - => - divnum - =>0 - - -File: m4.info, Node: Pushdef, Next: Indir, Prev: Defn, Up: Definitions - -5.6 Temporarily redefining macros -================================= - -It is possible to redefine a macro temporarily, reverting to the -previous definition at a later time. This is done with the builtins -`pushdef' and `popdef': - - -- Builtin: pushdef (NAME, [EXPANSION]) - -- Builtin: popdef (NAME...) - Analogous to `define' and `undefine'. - - These macros work in a stack-like fashion. A macro is temporarily - redefined with `pushdef', which replaces an existing definition of - NAME, while saving the previous definition, before the new one is - installed. If there is no previous definition, `pushdef' behaves - exactly like `define'. - - If a macro has several definitions (of which only one is - accessible), the topmost definition can be removed with `popdef'. - If there is no previous definition, `popdef' behaves like - `undefine'. - - The expansion of both `pushdef' and `popdef' is void. The macros - `pushdef' and `popdef' are recognized only with parameters. - - define(`foo', `Expansion one.') - => - foo - =>Expansion one. - pushdef(`foo', `Expansion two.') - => - foo - =>Expansion two. - pushdef(`foo', `Expansion three.') - => - pushdef(`foo', `Expansion four.') - => - popdef(`foo') - => - foo - =>Expansion three. - popdef(`foo', `foo') - => - foo - =>Expansion one. - popdef(`foo') - => - foo - =>foo - - If a macro with several definitions is redefined with `define', the -topmost definition is _replaced_ with the new definition. If it is -removed with `undefine', _all_ the definitions are removed, and not -only the topmost one. - - define(`foo', `Expansion one.') - => - foo - =>Expansion one. - pushdef(`foo', `Expansion two.') - => - foo - =>Expansion two. - define(`foo', `Second expansion two.') - => - foo - =>Second expansion two. - undefine(`foo') - => - foo - =>foo - - Local variables within macros are made with `pushdef' and `popdef'. -At the start of the macro a new definition is pushed, within the macro -it is manipulated and at the end it is popped, revealing the former -definition. - - It is possible to temporarily redefine a builtin with `pushdef' and -`defn'. - - -File: m4.info, Node: Indir, Next: Builtin, Prev: Pushdef, Up: Definitions - -5.7 Indirect call of macros -=========================== - -Any macro can be called indirectly with `indir': - - -- Builtin: indir (NAME, [ARGS...]) - Results in a call to the macro NAME, which is passed the rest of - the arguments ARGS. If NAME is not defined, an error message is - printed, and the expansion is void. - - The macro `indir' is recognized only with parameters. - - This can be used to call macros with computed or "invalid" names -(`define' allows such names to be defined): - - define(`$$internal$macro', `Internal macro (name `$0')') - => - $$internal$macro - =>$$internal$macro - indir(`$$internal$macro') - =>Internal macro (name $$internal$macro) - - The point is, here, that larger macro packages can have private -macros defined, that will not be called by accident. They can _only_ be -called through the builtin `indir'. - - One other point to observe is that argument collection occurs before -`indir' invokes NAME, so if argument collection changes the value of -NAME, that will be reflected in the final expansion. This is different -than the behavior when invoking macros directly, where the definition -that was in effect before argument collection is used. - - define(`f', `1') - => - f(define(`f', `2')) - =>1 - indir(`f', define(`f', `3')) - =>3 - indir(`f', undefine(`f')) - error-->m4:stdin:4: undefined macro `f' - => - - When handed the result of `defn' (*note Defn::) as one of its -arguments, `indir' defers to the invoked NAME for whether a token -representing a builtin is recognized or flattened to the empty string. - - indir(defn(`defn'), `divnum') - error-->m4:stdin:1: Warning: indir: invalid macro name ignored - => - indir(`define', defn(`defn'), `divnum') - error-->m4:stdin:2: Warning: define: invalid macro name ignored - => - indir(`define', `foo', defn(`divnum')) - => - foo - =>0 - indir(`divert', defn(`foo')) - error-->m4:stdin:5: empty string treated as 0 in builtin `divert' - => - - -File: m4.info, Node: Builtin, Prev: Indir, Up: Definitions - -5.8 Indirect call of builtins -============================= - -Builtin macros can be called indirectly with `builtin': - - -- Builtin: builtin (NAME, [ARGS...]) - Results in a call to the builtin NAME, which is passed the rest of - the arguments ARGS. If NAME does not name a builtin, an error - message is printed, and the expansion is void. - - The macro `builtin' is recognized only with parameters. - - This can be used even if NAME has been given another definition that -has covered the original, or been undefined so that no macro maps to -the builtin. - - pushdef(`define', `hidden') - => - undefine(`undefine') - => - define(`foo', `bar') - =>hidden - foo - =>foo - builtin(`define', `foo', defn(`divnum')) - => - foo - =>0 - builtin(`define', `foo', `BAR') - => - foo - =>BAR - undefine(`foo') - =>undefine(foo) - foo - =>BAR - builtin(`undefine', `foo') - => - foo - =>foo - - The NAME argument only matches the original name of the builtin, -even when the `--prefix-builtins' option (or `-P', *note Invoking m4: -Operation modes.) is in effect. This is different from `indir', which -only tracks current macro names. - - Note that `indir' and `builtin' can be used to invoke builtins -without arguments, even when they normally require parameters to be -recognized; but it will provoke a warning, and result in a void -expansion. - - builtin - =>builtin - builtin() - error-->m4:stdin:2: undefined builtin `' - => - builtin(`builtin') - error-->m4:stdin:3: Warning: too few arguments to builtin `builtin' - => - builtin(`builtin',) - error-->m4:stdin:4: undefined builtin `' - => - - -File: m4.info, Node: Conditionals, Next: Debugging, Prev: Definitions, Up: Top - -6 Conditionals, loops, and recursion -************************************ - -Macros, expanding to plain text, perhaps with arguments, are not quite -enough. We would like to have macros expand to different things, based -on decisions taken at run-time. For that, we need some kind of -conditionals. Also, we would like to have some kind of loop construct, -so we could do something a number of times, or while some condition is -true. - -* Menu: - -* Ifdef:: Testing if a macro is defined -* Ifelse:: If-else construct, or multibranch -* Shift:: Recursion in `m4' -* Forloop:: Iteration by counting -* Foreach:: Iteration by list contents - - -File: m4.info, Node: Ifdef, Next: Ifelse, Up: Conditionals - -6.1 Testing if a macro is defined -================================= - -There are two different builtin conditionals in `m4'. The first is -`ifdef': - - -- Builtin: ifdef (NAME, STRING-1, [STRING-2]) - If NAME is defined as a macro, `ifdef' expands to STRING-1, - otherwise to STRING-2. If STRING-2 is omitted, it is taken to be - the empty string (according to the normal rules). - - The macro `ifdef' is recognized only with parameters. - - ifdef(`foo', ``foo' is defined', ``foo' is not defined') - =>foo is not defined - define(`foo', `') - => - ifdef(`foo', ``foo' is defined', ``foo' is not defined') - =>foo is defined - ifdef(`no_such_macro', `yes', `no', `extra argument') - error-->m4:stdin:4: Warning: excess arguments to builtin `ifdef' ignored - =>no - - -File: m4.info, Node: Ifelse, Next: Shift, Prev: Ifdef, Up: Conditionals - -6.2 If-else construct, or multibranch -===================================== - -The other conditional, `ifelse', is much more powerful. It can be used -as a way to introduce a long comment, as an if-else construct, or as a -multibranch, depending on the number of arguments supplied: - - -- Builtin: ifelse (COMMENT) - -- Builtin: ifelse (STRING-1, STRING-2, EQUAL, [NOT-EQUAL]) - -- Builtin: ifelse (STRING-1, STRING-2, EQUAL-1, STRING-3, STRING-4, - EQUAL-2, ...) - Used with only one argument, the `ifelse' simply discards it and - produces no output. - - If called with three or four arguments, `ifelse' expands into - EQUAL, if STRING-1 and STRING-2 are equal (character for - character), otherwise it expands to NOT-EQUAL. A final fifth - argument is ignored, after triggering a warning. - - If called with six or more arguments, and STRING-1 and STRING-2 - are equal, `ifelse' expands into EQUAL-1, otherwise the first - three arguments are discarded and the processing starts again. - - The macro `ifelse' is recognized only with parameters. - - Using only one argument is a common `m4' idiom for introducing a -block comment, as an alternative to repeatedly using `dnl'. This -special usage is recognized by GNU `m4', so that in this case, the -warning about missing arguments is never triggered. - - ifelse(`some comments') - => - ifelse(`foo', `bar') - error-->m4:stdin:2: Warning: too few arguments to builtin `ifelse' - => - - Using three or four arguments provides decision points. - - ifelse(`foo', `bar', `true') - => - ifelse(`foo', `foo', `true') - =>true - define(`foo', `bar') - => - ifelse(foo, `bar', `true', `false') - =>true - ifelse(foo, `foo', `true', `false') - =>false - - Notice how the first argument was used unquoted; it is common to -compare the expansion of a macro with a string. With this macro, you -can now reproduce the behavior of many of the builtins, where the macro -is recognized only with arguments. - - define(`foo', `ifelse(`$#', `0', ``$0'', `arguments:$#')') - => - foo - =>foo - foo() - =>arguments:1 - foo(`a', `b', `c') - =>arguments:3 - - However, `ifelse' can take more than four arguments. If given more -than four arguments, `ifelse' works like a `case' or `switch' statement -in traditional programming languages. If STRING-1 and STRING-2 are -equal, `ifelse' expands into EQUAL-1, otherwise the procedure is -repeated with the first three arguments discarded. This calls for an -example: - - ifelse(`foo', `bar', `third', `gnu', `gnats') - error-->m4:stdin:1: Warning: excess arguments to builtin `ifelse' ignored - =>gnu - ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth') - => - ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth', `seventh') - =>seventh - ifelse(`foo', `bar', `3', `gnu', `gnats', `6', `7', `8') - error-->m4:stdin:4: Warning: excess arguments to builtin `ifelse' ignored - =>7 - - Naturally, the normal case will be slightly more advanced than these -examples. A common use of `ifelse' is in macros implementing loops of -various kinds. - - -File: m4.info, Node: Shift, Next: Forloop, Prev: Ifelse, Up: Conditionals - -6.3 Recursion in `m4' -===================== - -There is no direct support for loops in `m4', but macros can be -recursive. There is no limit on the number of recursion levels, other -than those enforced by your hardware and operating system. - - Loops can be programmed using recursion and the conditionals -described previously. - - There is a builtin macro, `shift', which can, among other things, be -used for iterating through the actual arguments to a macro: - - -- Builtin: shift (ARG1, ...) - Takes any number of arguments, and expands to all its arguments - except ARG1, separated by commas, with each argument quoted. - - The macro `shift' is recognized only with parameters. - - shift - =>shift - shift(`bar') - => - shift(`foo', `bar', `baz') - =>bar,baz - - An example of the use of `shift' is this macro: - - -- Composite: reverse (...) - Takes any number of arguments, and reverses their order. - - It is implemented as: - - define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'', - `reverse(shift($@)), `$1'')') - => - reverse - => - reverse(`foo') - =>foo - reverse(`foo', `bar', `gnats', `and gnus') - =>and gnus, gnats, bar, foo - - While not a very interesting macro, it does show how simple loops -can be made with `shift', `ifelse' and recursion. It also shows that -`shift' is usually used with `$@'. Sometimes, a recursive algorithm -requires adding quotes to each element: - - -- Composite: quote (...) - -- Composite: dquote (...) - -- Composite: dquote_elt (...) - Takes any number of arguments, and adds quoting. With `quote', - only one level of quoting is added, effectively removing whitespace - after commas and turning multiple arguments into a single string. - With `dquote', two levels of quoting are added, one around each - element, and one around the list. And with `dquote_elt', two - levels of quoting are added around each element. - - An actual implementation of these three macros is distributed as -`m4-1.4.8/examples/quote.m4' in this package. First, let's examine -their usage: - - include(`quote.m4') - => - -quote-dquote-dquote_elt- - =>---- - -quote()-dquote()-dquote_elt()- - =>--`'-`'- - -quote(`1')-dquote(`1')-dquote_elt(`1')- - =>-1-`1'-`1'- - -quote(`1', `2')-dquote(`1', `2')-dquote_elt(`1', `2')- - =>-1,2-`1',`2'-`1',`2'- - define(`n', `$#')dnl - -n(quote(`1', `2'))-n(dquote(`1', `2'))-n(dquote_elt(`1', `2'))- - =>-1-1-2- - dquote(dquote_elt(`1', `2')) - =>``1'',``2'' - dquote_elt(dquote(`1', `2')) - =>``1',`2'' - - The last two lines show that when given two arguments, `dquote' -results in one string, while `dquote_elt' results in two. Now, examine -the implementation. Note that `quote' and `dquote_elt' make decisions -based on their number of arguments, so that when called without -arguments, they result in nothing instead of a quoted empty string; -this is so that it is possible to distinquish between no arguments and -an empty first argument. `dquote', on the other hand, results in a -string no matter what, since it is still possible to tell whether it -was invoked without arguments based on the resulting string. - - undivert(`quote.m4')dnl - =>divert(`-1') - =># quote(args) - convert args to single-quoted string - =>define(`quote', `ifelse(`$#', `0', `', ``$*'')') - =># dquote(args) - convert args to quoted list of quoted strings - =>define(`dquote', ``$@'') - =># dquote_elt(args) - convert args to list of double-quoted strings - =>define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''', - => ```$1'',$0(shift($@))')') - =>divert`'dnl - - -File: m4.info, Node: Forloop, Next: Foreach, Prev: Shift, Up: Conditionals - -6.4 Iteration by counting -========================= - -Here is an example of a loop macro that implements a simple for loop. - - -- Composite: forloop (ITERATOR, START, END, TEXT) - Takes the name in ITERATOR, which must be a valid macro name, and - successively assign it each integer value from START to END, - inclusive. For each assignment to ITERATOR, append TEXT to the - expansion of the `forloop'. TEXT may refer to ITERATOR. Any - definition of ITERATOR prior to this invocation is restored. - - It can, for example, be used for simple counting: - - include(`forloop.m4') - => - forloop(`i', `1', `8', `i ') - =>1 2 3 4 5 6 7 8 - - For-loops can be nested, like: - - include(`forloop.m4') - => - forloop(`i', `1', `4', `forloop(`j', `1', `8', ` (i, j)') - ') - => (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8) - => (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8) - => (3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6) (3, 7) (3, 8) - => (4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6) (4, 7) (4, 8) - => - - The implementation of the `forloop' macro is fairly straightforward. -The `forloop' macro itself is simply a wrapper, which saves the -previous definition of the first argument, calls the internal macro -`_forloop', and re-establishes the saved definition of the first -argument. - - The macro `_forloop' expands the fourth argument once, and tests to -see if the iterator has reached the final value. If it has not -finished, it increments the iterator (using the predefined macro -`incr', *note Incr::), and recurses. - - Here is an actual implementation of `forloop', distributed as -`m4-1.4.8/examples/forloop.m4' in this package: - - undivert(`forloop.m4')dnl - =>divert(`-1') - =># forloop(var, from, to, stmt) - simple version - =>define(`forloop', `pushdef(`$1', `$2')_forloop($@)popdef(`$1')') - =>define(`_forloop', - => `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@)')') - =>divert`'dnl - - Notice the careful use of quotes. Certain macro arguments are left -unquoted, each for its own reason. Try to find out _why_ these -arguments are left unquoted, and see what happens if they are quoted. -(As presented, these two macros are useful but not very robust for -general use. They lack even basic error handling for cases like START -less than END, END not numeric, or ITERATOR not being a macro name. -See if you can improve these macros; or *note Answers: Improved -forloop.). - - -File: m4.info, Node: Foreach, Prev: Forloop, Up: Conditionals - -6.5 Iteration by list contents -============================== - -Here is an example of a loop macro that implements list iteration. - - -- Composite: foreach (ITERATOR, PAREN-LIST, TEXT) - -- Composite: foreachq (ITERATOR, QUOTE-LIST, TEXT) - Takes the name in ITERATOR, which must be a valid macro name, and - successively assign it each value from PAREN-LIST or QUOTE-LIST. - In `foreach', PAREN-LIST is a comma-separated list of elements - contained in parentheses. In `foreachq', QUOTE-LIST is a - comma-separated list of elements contained in a quoted string. - For each assignment to ITERATOR, append TEXT to the overall - expansion. TEXT may refer to ITERATOR. Any definition of - ITERATOR prior to this invocation is restored. - - As an example, this displays each word in a list inside of a -sentence, using an implementation of `foreach' distributed as -`m4-1.4.8/examples/foreach.m4', and `foreachq' in -`m4-1.4.8/examples/foreachq.m4'. - - include(`foreach.m4') - => - foreach(`x', (foo, bar, foobar), `Word was: x - ')dnl - =>Word was: foo - =>Word was: bar - =>Word was: foobar - include(`foreachq.m4') - => - foreachq(`x', `foo, bar, foobar', `Word was: x - ')dnl - =>Word was: foo - =>Word was: bar - =>Word was: foobar - - It is possible to be more complex; each element of the PAREN-LIST or -QUOTE-LIST can itself be a list, to pass as further arguments to a -helper macro. This example generates a shell case statement: - - include(`foreach.m4') - => - define(`_case', ` $1) - $2=" $1";; - ')dnl - define(`_cat', `$1$2')dnl - case $`'1 in - =>case $1 in - foreach(`x', `(`(`a', `vara')', `(`b', `varb')', `(`c', `varc')')', - `_cat(`_case', x)')dnl - => a) - => vara=" a";; - => b) - => varb=" b";; - => c) - => varc=" c";; - esac - =>esac - - The implementation of the `foreach' macro is a bit more involved; it -is a wrapper around two helper macros. First, `_arg1' is needed to -grab the first element of a list. Second, `_foreach' implements the -recursion, successively walking through the original list. Here is a -simple implementation of `foreach': - - undivert(`foreach.m4')dnl - =>divert(`-1') - =># foreach(x, (item_1, item_2, ..., item_n), stmt) - =># parenthesized list, simple version - =>define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')') - =>define(`_arg1', `$1') - =>define(`_foreach', `ifelse(`$2', `()', `', - => `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')') - =>divert`'dnl - - Unfortunately, that implementation is not robust to macro names as -list elements. Each iteration of `_foreach' is stripping another layer -of quotes, leading to erratic results if list elements are not already -fully expanded. The first cut at implementing `foreachq' takes this -into account. Also, when using quoted elements in a PAREN-LIST, the -overall list must be quoted. A QUOTE-LIST has the nice property of -requiring fewer characters to create a list containing the same quoted -elements. To see the difference between the two macros, we attempt to -pass double-quoted macro names in a list, expecting the macro name on -output after one layer of quotes is removed during list iteration and -the final layer removed during the final rescan: - - define(`a', `1')define(`b', `2')define(`c', `3') - => - include(`foreach.m4') - => - include(`foreachq.m4') - => - foreach(`x', `(``a'', ``(b'', ``c)'')', `x - ') - =>1 - =>(2)1 - => - =>, x - =>) - foreachq(`x', ```a'', ``(b'', ``c)''', `x - ')dnl - =>a - =>(b - =>c) - - Obviously, `foreachq' did a better job; here is its implementation: - - undivert(`foreachq.m4')dnl - =>include(`quote.m4')dnl - =>divert(`-1') - =># foreachq(x, `item_1, item_2, ..., item_n', stmt) - =># quoted list, simple version - =>define(`foreachq', `pushdef(`$1')_foreachq($@)popdef(`$1')') - =>define(`_arg1', `$1') - =>define(`_foreachq', `ifelse(quote($2), `', `', - => `define(`$1', `_arg1($2)')$3`'$0(`$1', `shift($2)', `$3')')') - =>divert`'dnl - - Notice that `_foreachq' had to use the helper macro `quote' defined -earlier (*note Shift::), to ensure that the embedded `ifelse' call does -not go haywire if a list element contains a comma. Unfortunately, this -implementation of `foreachq' has its own severe flaw. Whereas the -`foreach' implementation was linear, this macro is quadratic in the -number of list elements, and is much more likely to trip up the limit -set by the command line option `--nesting-limit' (or `-L', *note -Invoking m4: Limits control.). (It is possible to have robust -iteration with linear behavior for either list style. See if you can -learn from the best elements of both of these implementations to create -robust macros; or *note Answers: Improved foreach.). - - -File: m4.info, Node: Debugging, Next: Input Control, Prev: Conditionals, Up: Top - -7 How to debug macros and input -******************************* - -When writing macros for `m4', they often do not work as intended on the -first try (as is the case with most programming languages). -Fortunately, there is support for macro debugging in `m4'. - -* Menu: - -* Dumpdef:: Displaying macro definitions -* Trace:: Tracing macro calls -* Debug Levels:: Controlling debugging output -* Debug Output:: Saving debugging output - - -File: m4.info, Node: Dumpdef, Next: Trace, Up: Debugging - -7.1 Displaying macro definitions -================================ - -If you want to see what a name expands into, you can use the builtin -`dumpdef': - - -- Builtin: dumpdef ([NAMES...]) - Accepts any number of arguments. If called without any arguments, - it displays the definitions of all known names, otherwise it - displays the definitions of the NAMES given. The output is - printed to the current debug file (usually standard error), and is - sorted by name. If an unknown name is encountered, a warning is - printed. - - The expansion of `dumpdef' is void. - - define(`foo', `Hello world.') - => - dumpdef(`foo') - error-->foo: `Hello world.' - => - dumpdef(`define') - error-->define: - => - - The last example shows how builtin macros definitions are displayed. -The definition that is dumped corresponds to what would occur if the -macro were to be called at that point, even if other definitions are -still live due to redefining a macro during argument collection. - - pushdef(`f', ``$0'1')pushdef(`f', ``$0'2') - => - f(popdef(`f')dumpdef(`f')) - error-->f: ``$0'1' - =>f2 - f(popdef(`f')dumpdef(`f')) - error-->m4:stdin:3: undefined macro `f' - =>f1 - - *Note Debug Levels::, for information on controlling the details of -the display. - - -File: m4.info, Node: Trace, Next: Debug Levels, Prev: Dumpdef, Up: Debugging - -7.2 Tracing macro calls -======================= - -It is possible to trace macro calls and expansions through the builtins -`traceon' and `traceoff': - - -- Builtin: traceon ([NAMES...]) - -- Builtin: traceoff ([NAMES...]) - When called without any arguments, `traceon' and `traceoff' will - turn tracing on and off, respectively, for all defined macros. - - When called with arguments, only the macros listed in NAMES are - affected, whether or not they are currently defined. - - The expansion of `traceon' and `traceoff' is void. - - Whenever a traced macro is called and the arguments have been -collected, the call is displayed. If the expansion of the macro call -is not void, the expansion can be displayed after the call. The output -is printed to the current debug file (defaulting to standard error, -*note Debug Output::). - - define(`foo', `Hello World.') - => - define(`echo', `$@') - => - traceon(`foo', `echo') - => - foo - error-->m4trace: -1- foo -> `Hello World.' - =>Hello World. - echo(`gnus', `and gnats') - error-->m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' - =>gnus,and gnats - - The number between dashes is the depth of the expansion. It is one -most of the time, signifying an expansion at the outermost level, but it -increases when macro arguments contain unquoted macro calls. The -maximum number that will appear between dashes is controlled by the -option `--nesting-limit' (*note Invoking m4: Limits control.). - - Tracing by name is an attribute that is preserved whether the macro -is defined or not. This allows the `-t' option to select macros to -trace before those macros are defined. - - traceoff(`foo') - => - traceon(`foo') - => - foo - =>foo - define(`foo', `bar') - => - foo - error-->m4trace: -1- foo -> `bar' - =>bar - undefine(`foo') - => - ifdef(`foo', `yes', `no') - =>no - indir(`foo') - error-->m4:stdin:8: undefined macro `foo' - => - define(`foo', `blah') - => - foo - error-->m4trace: -1- foo -> `blah' - =>blah - traceoff - => - foo - =>blah - - Tracing even works on builtins. However, `defn' (*note Defn::) does -not transfer tracing status. - - traceon(`eval', `m4_divnum') - => - define(`m4_eval', defn(`eval')) - => - define(`m4_divnum', defn(`divnum')) - => - eval(divnum) - error-->m4trace: -1- eval(`0') -> `0' - =>0 - m4_eval(m4_divnum) - error-->m4trace: -2- m4_divnum -> `0' - =>0 - - *Note Debug Levels::, for information on controlling the details of -the display. - - -File: m4.info, Node: Debug Levels, Next: Debug Output, Prev: Trace, Up: Debugging - -7.3 Controlling debugging output -================================ - -The `-d' option to `m4' (*note Invoking m4: Debugging options.) -controls the amount of details presented, when using the macros -described in the preceding sections. - - The FLAGS following the option can be one or more of the following: - -`a' - Show the actual arguments in each macro call. This applies to all - macro calls if the `t' flag is used, otherwise only the macros - covered by calls of `traceon'. - -`c' - Show several trace lines for each macro call. A line is shown - when the macro is seen, but before the arguments are collected; a - second line when the arguments have been collected and a third - line after the call has completed. - -`e' - Show the expansion of each macro call, if it is not void. This - applies to all macro calls if the `t' flag is used, otherwise only - the macros covered by calls of `traceon'. - -`f' - Show the name of the current input file in each trace output line. - -`i' - Print a message each time the current input file is changed, - giving file name and input line number. - -`l' - Show the current input line number in each trace output line. - -`p' - Print a message when a named file is found through the path search - mechanism (*note Search Path::), giving the actual file name used. - -`q' - Quote actual arguments and macro expansions in the display with the - current quotes. - -`t' - Trace all macro calls made in this invocation of `m4'. - -`x' - Add a unique `macro call id' to each line of the trace output. - This is useful in connection with the `c' flag above. - -`V' - A shorthand for all of the above flags. - - If no flags are specified with the `-d' option, the default is -`aeq'. The examples throughout this manual assume the default flags. - - There is a builtin macro `debugmode', which allows on-the-fly -control of the debugging output format: - - -- Builtin: debugmode ([FLAGS]) - The argument FLAGS should be a subset of the letters listed above. - As special cases, if the argument starts with a `+', the flags are - added to the current debug flags, and if it starts with a `-', they - are removed. If no argument is present, all debugging flags are - cleared (as if no `-d' was given), and with an empty argument the - flags are reset to the default of `aeq'. - - The expansion of `debugmode' is void. - - define(`foo', `FOO') - => - traceon(`foo') - => - debugmode() - => - foo - error-->m4trace: -1- foo -> `FOO' - =>FOO - debugmode - => - foo - error-->m4trace: -1- foo - =>FOO - debugmode(`+l') - => - foo - error-->m4trace:8: -1- foo - =>FOO - - -File: m4.info, Node: Debug Output, Prev: Debug Levels, Up: Debugging - -7.4 Saving debugging output -=========================== - -Debug and tracing output can be redirected to files using either the -`--debugfile' option to `m4' (*note Invoking m4: Debugging options.), -or with the builtin macro `debugfile': - - -- Builtin: debugfile ([FILE]) - Sends all further debug and trace output to FILE, opened in append - mode. If FILE is the empty string, debug and trace output are - discarded. If `debugfile' is called without any arguments, debug - and trace output are sent to standard error. This does not affect - warnings, error messages, or `errprint' output, which are always - sent to standard error. If FILE cannot be opened, the current - debug file is unchanged, and an error is issued. - - The expansion of `debugfile' is void. - - traceon(`divnum') - => - divnum(`extra') - error-->m4:stdin:2: Warning: excess arguments to builtin `divnum' ignored - error-->m4trace: -1- divnum(`extra') -> `0' - =>0 - debugfile() - => - divnum(`extra') - error-->m4:stdin:4: Warning: excess arguments to builtin `divnum' ignored - =>0 - debugfile - => - divnum - error-->m4trace: -1- divnum -> `0' - =>0 - - -File: m4.info, Node: Input Control, Next: File Inclusion, Prev: Debugging, Up: Top - -8 Input control -*************** - -This chapter describes various builtin macros for controlling the input -to `m4'. - -* Menu: - -* Dnl:: Deleting whitespace in input -* Changequote:: Changing the quote characters -* Changecom:: Changing the comment delimiters -* Changeword:: Changing the lexical structure of words -* M4wrap:: Saving text until end of input - - -File: m4.info, Node: Dnl, Next: Changequote, Up: Input Control - -8.1 Deleting whitespace in input -================================ - -The builtin `dnl' stands for "Discard to Next Line": - - -- Builtin: dnl - All characters, up to and including the next newline, are discarded - without performing any macro expansion. A warning is issued if - the end of the file is encountered without a newline. - - The expansion of `dnl' is void. - - It is often used in connection with `define', to remove the newline -that follows the call to `define'. Thus - - define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. - foo - =>Macro foo. - - The input up to and including the next newline is discarded, as -opposed to the way comments are treated (*note Comments::). - - Usually, `dnl' is immediately followed by an end of line or some -other whitespace. GNU `m4' will produce a warning diagnostic if `dnl' -is followed by an open parenthesis. In this case, `dnl' will collect -and process all arguments, looking for a matching close parenthesis. -All predictable side effects resulting from this collection will take -place. `dnl' will return no output. The input following the matching -close parenthesis up to and including the next newline, on whatever -line containing it, will still be discarded. - - dnl(`args are ignored, but side effects occur', - define(`foo', `like this')) while this text is ignored: undefine(`foo') - error-->m4:stdin:1: Warning: excess arguments to builtin `dnl' ignored - See how `foo' was defined, foo? - =>See how foo was defined, like this? - - If the end of file is encountered without a newline character, a -warning is issued and dnl stops consuming input. - - m4wrap(`m4wrap(`2 hi - ')0 hi dnl 1 hi') - => - define(`hi', `HI') - => - ^D - error-->m4:stdin:1: Warning: end of file treated as newline - =>0 HI 2 HI - - -File: m4.info, Node: Changequote, Next: Changecom, Prev: Dnl, Up: Input Control - -8.2 Changing the quote characters -================================= - -The default quote delimiters can be changed with the builtin -`changequote': - - -- Builtin: changequote ([START = ``'], [END = `'']) - This sets START as the new begin-quote delimiter and END as the - new end-quote delimiter. If both arguments are missing, the - default quotes (``' and `'') are used. If START is void, then - quoting is disabled. Otherwise, if END is missing or void, the - default end-quote delimiter (`'') is used. The quote delimiters - can be of any length. - - The expansion of `changequote' is void. - - changequote(`[', `]') - => - define([foo], [Macro [foo].]) - => - foo - =>Macro foo. - - The quotation strings can safely contain eight-bit characters. If -no single character is appropriate, START and END can be of any length. -Other implementations cap the delimiter length to five characters, but -GNU has no inherent limit. - - changequote(`[[[', `]]]') - => - define([[[foo]]], [[[Macro [[[[[foo]]]]].]]]) - => - foo - =>Macro [[foo]]. - - Calling `changequote' with START as the empty string will -effectively disable the quoting mechanism, leaving no way to quote text. -However, using an empty string is not portable, as some other -implementations of `m4' revert to the default quoting, while others -preserve the prior non-empty delimiter. If START is not empty, then an -empty END will use the default end-quote delimiter of `'', as -otherwise, it would be impossible to end a quoted string. Again, this -is not portable, as some other `m4' implementations reuse START as the -end-quote delimiter, while others preserve the previous non-empty -value. Omitting both arguments restores the default begin-quote and -end-quote delimiters; fortunately this behavior is portable to all -implementations of `m4'. - - define(`foo', `Macro `FOO'.') - => - changequote(`', `') - => - foo - =>Macro `FOO'. - `foo' - =>`Macro `FOO'.' - changequote(`,) - => - foo - =>Macro FOO. - - There is no way in `m4' to quote a string containing an unmatched -begin-quote, except using `changequote' to change the current quotes. - - If the quotes should be changed from, say, `[' to `[[', temporary -quote characters have to be defined. To achieve this, two calls of -`changequote' must be made, one for the temporary quotes and one for -the new quotes. - - Macros are recognized in preference to the begin-quote string, so if -a prefix of START can be recognized as part of a potential macro name, -the quoting mechanism is effectively disabled. Unless you use -`changeword' (*note Changeword::), this means that START should not -begin with a letter, digit, or `_' (underscore). However, even though -quoted strings are not recognized, the quote characters can still be -discerned in macro expansion and in trace output. - - define(`echo', `$@') - => - define(`hi', `HI') - => - changequote(`q', `Q') - => - q hi Q hi - =>q HI Q HI - echo(hi) - =>qHIQ - changequote - => - changequote(`-', `EOF') - => - - hi EOF hi - => hi HI - changequote - => - changequote(`1', `2') - => - hi1hi2 - =>hi1hi2 - hi 1hi2 - =>HI hi - - Quotes are recognized in preference to argument collection. In -particular, if START is a single `(', then argument collection is -effectively disabled. For portability with other implementations, it -is a good idea to avoid `(', `,', and `)' as the first character in -START. - - define(`echo', `$#:$@:') - => - define(`hi', `HI') - => - changequote(`(',`)') - => - echo(hi) - =>0::hi - changequote - => - changequote(`((', `))') - => - echo(hi) - =>1:HI: - echo((hi)) - =>0::hi - changequote - => - changequote(`,', `)') - => - echo(hi,hi)bye) - =>1:HIhibye: - - If END is a prefix of START, the end-quote will be recognized in -preference to a nested begin-quote. In particular, changing the quotes -to have the same string for START and END disables nesting of quotes. -When quote nesting is disabled, it is impossible to double-quote -strings across macro expansions, so using the same string is not done -very often. - - define(`hi', `HI') - => - changequote(`""', `"') - => - ""hi"""hi" - =>hihi - ""hi" ""hi" - =>hi hi - ""hi"" "hi" - =>hi" "HI" - changequote - => - `hi`hi'hi' - =>hi`hi'hi - changequote(`"', `"') - => - "hi"hi"hi" - =>hiHIhi - - It is an error if the end of file occurs within a quoted string. - - `hello world' - =>hello world - `dangling quote - ^D - error-->m4:stdin:2: ERROR: end of file in string - - -File: m4.info, Node: Changecom, Next: Changeword, Prev: Changequote, Up: Input Control - -8.3 Changing the comment delimiters -=================================== - -The default comment delimiters can be changed with the builtin macro -`changecom': - - -- Builtin: changecom ([START], [END = `']) - This sets START as the new begin-comment delimiter and END as the - new end-comment delimiter. If both arguments are missing, or - START is void, then comments are disabled. Otherwise, if END is - missing or void, the default end-comment delimiter of newline is - used. The comment delimiters can be of any length. - - The expansion of `changecom' is void. - - define(`comment', `COMMENT') - => - # A normal comment - =># A normal comment - changecom(`/*', `*/') - => - # Not a comment anymore - =># Not a COMMENT anymore - But: /* this is a comment now */ while this is not a comment - =>But: /* this is a comment now */ while this is not a COMMENT - - Note how comments are copied to the output, much as if they were -quoted strings. If you want the text inside a comment expanded, quote -the begin-comment delimiter. - - Calling `changecom' without any arguments, or with START as the -empty string, will effectively disable the commenting mechanism. To -restore the original comment start of `#', you must explicitly ask for -it. If START is not empty, then an empty END will use the default -end-comment delimiter of newline, as otherwise, it would be impossible -to end a comment. However, this is not portable, as some other `m4' -implementations preserve the previous non-empty delimiters instead. - - define(`comment', `COMMENT') - => - changecom - => - # Not a comment anymore - =># Not a COMMENT anymore - changecom(`#', `') - => - # comment again - =># comment again - - The comment strings can safely contain eight-bit characters. If no -single character is appropriate, START and END can be of any length. -Other implementations cap the delimiter length to five characters, but -GNU has no inherent limit. - - Comments are recognized in preference to macros. However, this is -not compatible with other implementations, where macros and even quoting -takes precedence over comments, so it may change in a future release. -For portability, this means that START should not begin with a letter, -digit, or `_' (underscore), and that neither the start-quote nor the -start-comment string should be a prefix of the other. - - define(`hi', `HI') - => - define(`hi1hi2', `hello') - => - changecom(`q', `Q') - => - q hi Q hi - =>q hi Q HI - changecom(`1', `2') - => - hi1hi2 - =>hello - hi 1hi2 - =>HI 1hi2 - - Comments are recognized in preference to argument collection. In -particular, if START is a single `(', then argument collection is -effectively disabled. For portability with other implementations, it -is a good idea to avoid `(', `,', and `)' as the first character in -START. - - define(`echo', `$#:$@:') - => - define(`hi', `HI') - => - changecom(`(',`)') - => - echo(hi) - =>0::(hi) - changecom - => - changecom(`((', `))') - => - echo(hi) - =>1:HI: - echo((hi)) - =>0::((hi)) - changecom(`,', `)') - => - echo(hi,hi)bye) - =>1:HI,hi)bye: - - It is an error if the end of file occurs within a comment. - - changecom(`/*', `*/') - => - /*dangling comment - ^D - error-->m4:stdin:2: ERROR: end of file in comment - - -File: m4.info, Node: Changeword, Next: M4wrap, Prev: Changecom, Up: Input Control - -8.4 Changing the lexical structure of words -=========================================== - - The macro `changeword' and all associated functionality is - experimental. It is only available if the `--enable-changeword' - option was given to `configure', at GNU `m4' installation time. - The functionality will go away in the future, to be replaced by - other new features that are more efficient at providing the same - capabilities. _Do not rely on it_. Please direct your comments - about it the same way you would do for bugs. - - A file being processed by `m4' is split into quoted strings, words -(potential macro names) and simple tokens (any other single character). -Initially a word is defined by the following regular expression: - - [_a-zA-Z][_a-zA-Z0-9]* - - Using `changeword', you can change this regular expression: - - -- Optional builtin: changeword (REGEX) - Changes the regular expression for recognizing macro names to be - REGEX. If REGEX is empty, use `[_a-zA-Z][_a-zA-Z0-9]*'. REGEX - must obey the constraint that every prefix of the desired final - pattern is also accepted by the regular expression. If REGEX - contains grouping parentheses, the macro invoked is the portion - that matched the first group, rather than the entire matching - string. - - The expansion of `changeword' is void. The macro `changeword' is - recognized only with parameters. - - Relaxing the lexical rules of `m4' might be useful (for example) if -you wanted to apply translations to a file of numbers: - - ifdef(`changeword', `', `errprint(` skipping: no changeword support - ')m4exit(`77')')dnl - changeword(`[_a-zA-Z0-9]+') - => - define(`1', `0')1 - =>0 - - Tightening the lexical rules is less useful, because it will -generally make some of the builtins unavailable. You could use it to -prevent accidental call of builtins, for example: - - ifdef(`changeword', `', `errprint(` skipping: no changeword support - ')m4exit(`77')')dnl - define(`_indir', defn(`indir')) - => - changeword(`_[_a-zA-Z0-9]*') - => - esyscmd(`foo') - =>esyscmd(foo) - _indir(`esyscmd', `echo hi') - =>hi - => - - Because `m4' constructs its words a character at a time, there is a -restriction on the regular expressions that may be passed to -`changeword'. This is that if your regular expression accepts `foo', -it must also accept `f' and `fo'. - - ifdef(`changeword', `', `errprint(` skipping: no changeword support - ')m4exit(`77')')dnl - define(`foo - ', `bar - ') - => - dnl This example wants to recognize changeword, dnl, and `foo\n'. - dnl First, we check that our regexp will match. - regexp(`changeword', `[cd][a-z]*\|foo[ - ]') - =>0 - regexp(`foo - ', `[cd][a-z]*\|foo[ - ]') - =>0 - regexp(`f', `[cd][a-z]*\|foo[ - ]') - =>-1 - foo - =>foo - changeword(`[cd][a-z]*\|foo[ - ]') - => - dnl Even though `foo\n' matches, we forgot to allow `f'. - foo - =>foo - changeword(`[cd][a-z]*\|fo*[ - ]?') - => - dnl Now we can call `foo\n'. - foo - =>bar - - `changeword' has another function. If the regular expression -supplied contains any grouped subexpressions, then text outside the -first of these is discarded before symbol lookup. So: - - ifdef(`changeword', `', `errprint(` skipping: no changeword support - ')m4exit(`77')')dnl - ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics - ')m4exit(`77')')dnl - changecom(`/*', `*/')dnl - define(`foo', `bar')dnl - changeword(`#\([_a-zA-Z0-9]*\)') - => - #esyscmd(`echo foo \#foo') - =>foo bar - => - - `m4' now requires a `#' mark at the beginning of every macro -invocation, so one can use `m4' to preprocess plain text without losing -various words like `divert'. - - In `m4', macro substitution is based on text, while in TeX, it is -based on tokens. `changeword' can throw this difference into relief. -For example, here is the same idea represented in TeX and `m4'. First, -the TeX version: - - \def\a{\message{Hello}} - \catcode`\@=0 - \catcode`\\=12 - @a - @bye - =>Hello - -Then, the `m4' version: - - ifdef(`changeword', `', `errprint(` skipping: no changeword support - ')m4exit(`77')')dnl - define(`a', `errprint(`Hello')')dnl - changeword(`@\([_a-zA-Z0-9]*\)') - => - @a - =>errprint(Hello) - - In the TeX example, the first line defines a macro `a' to print the -message `Hello'. The second line defines <@> to be usable instead of -<\> as an escape character. The third line defines <\> to be a normal -printing character, not an escape. The fourth line invokes the macro -`a'. So, when TeX is run on this file, it displays the message `Hello'. - - When the `m4' example is passed through `m4', it outputs -`errprint(Hello)'. The reason for this is that TeX does lexical -analysis of macro definition when the macro is _defined_. `m4' just -stores the text, postponing the lexical analysis until the macro is -_used_. - - You should note that using `changeword' will slow `m4' down by a -factor of about seven, once it is changed to something other than the -default regular expression. You can invoke `changeword' with the empty -string to restore the default word definition, and regain the parsing -speed. - - -File: m4.info, Node: M4wrap, Prev: Changeword, Up: Input Control - -8.5 Saving text until end of input -================================== - -It is possible to `save' some text until the end of the normal input has -been seen. Text can be saved, to be read again by `m4' when the normal -input has been exhausted. This feature is normally used to initiate -cleanup actions before normal exit, e.g., deleting temporary files. - - To save input text, use the builtin `m4wrap': - - -- Builtin: m4wrap (STRING, ...) - Stores STRING in a safe place, to be reread when end of input is - reached. As a GNU extension, additional arguments are - concatenated with a space to the STRING. - - The expansion of `m4wrap' is void. The macro `m4wrap' is - recognized only with parameters. - - define(`cleanup', `This is the `cleanup' action. - ') - => - m4wrap(`cleanup') - => - This is the first and last normal input line. - =>This is the first and last normal input line. - ^D - =>This is the cleanup action. - - The saved input is only reread when the end of normal input is seen, -and not if `m4exit' is used to exit `m4'. - - It is safe to call `m4wrap' from saved text, but then the order in -which the saved text is reread is undefined. If `m4wrap' is not used -recursively, the saved pieces of text are reread in the opposite order -in which they were saved (LIFO--last in, first out). However, this -behavior is likely to change in a future release, to match POSIX, so -you should not depend on this order. - - Here is an example of implementing a factorial function using -`m4wrap': - - define(`f', `ifelse(`$1', `0', `Answer: 0!=1 - ', eval(`$1>1'), `0', `Answer: $2$1=eval(`$2$1') - ', `m4wrap(`f(decr(`$1'), `$2$1*')')')') - => - f(`10') - => - ^D - =>Answer: 10*9*8*7*6*5*4*3*2*1=3628800 - - Invocations of `m4wrap' at the same recursion level are concatenated -and rescanned as usual: - - define(`aa', `AA - ') - => - m4wrap(`a')m4wrap(`a') - => - ^D - =>AA - -however, the transition between recursion levels behaves like an end of -file condition between two input files. - - m4wrap(`m4wrap(`)')len(abc') - => - ^D - error-->m4:stdin:1: ERROR: end of file in argument list - - -File: m4.info, Node: File Inclusion, Next: Diversions, Prev: Input Control, Up: Top - -9 File inclusion -**************** - -`m4' allows you to include named files at any point in the input. - -* Menu: - -* Include:: Including named files -* Search Path:: Searching for include files - - -File: m4.info, Node: Include, Next: Search Path, Up: File Inclusion - -9.1 Including named files -========================= - -There are two builtin macros in `m4' for including files: - - -- Builtin: include (FILE) - -- Builtin: sinclude (FILE) - Both macros cause the file named FILE to be read by `m4'. When - the end of the file is reached, input is resumed from the previous - input file. - - The expansion of `include' and `sinclude' is therefore the - contents of FILE. - - If FILE does not exist (or cannot be read), the expansion is void, - and `include' will fail with an error while `sinclude' is silent. - The empty string counts as a file that does not exist. - - The macros `include' and `sinclude' are recognized only with - parameters. - - include(`none') - error-->m4:stdin:1: cannot open `none': No such file or directory - => - include() - error-->m4:stdin:2: cannot open `': No such file or directory - => - sinclude(`none') - => - sinclude() - => - - The rest of this section assumes that `m4' is invoked with the `-I' -option (*note Invoking m4: Preprocessor features.) pointing to the -`m4-1.4.8/examples' directory shipped as part of the GNU `m4' package. -The file `m4-1.4.8/examples/incl.m4' in the distribution contains the -lines: - - Include file start - foo - Include file end - - Normally file inclusion is used to insert the contents of a file -into the input stream. The contents of the file will be read by `m4' -and macro calls in the file will be expanded: - - define(`foo', `FOO') - => - include(`incl.m4') - =>Include file start - =>FOO - =>Include file end - => - - The fact that `include' and `sinclude' expand to the contents of the -file can be used to define macros that operate on entire files. Here -is an example, which defines `bar' to expand to the contents of -`incl.m4': - - define(`bar', include(`incl.m4')) - => - This is `bar': >>bar<< - =>This is bar: >>Include file start - =>foo - =>Include file end - =><< - - This use of `include' is not trivial, though, as files can contain -quotes, commas, and parentheses, which can interfere with the way the -`m4' parser works. GNU `m4' seamlessly concatenates the file contents -with the next character, even if the included file ended in the middle -of a comment, string, or macro call. These conditions are only treated -as end of file errors if specified as input files on the command line. - - In GNU `m4', an alternative method of reading files is using -`undivert' (*note Undivert::) on a named file. - - -File: m4.info, Node: Search Path, Prev: Include, Up: File Inclusion - -9.2 Searching for include files -=============================== - -GNU `m4' allows included files to be found in other directories than -the current working directory. - - If the `--prepend-include' or `-B' command-line option was provided -(*note Invoking m4: Preprocessor features.), those directories are -searched first, in reverse order that those options were listed on the -command line. Then `m4' looks in the current working directory. Next -comes the directories specified with the `--include' or `-I' option, in -the order found on the command line. Finally, if the `M4PATH' -environment variable is set, it is expected to contain a -colon-separated list of directories, which will be searched in order. - - If the automatic search for include-files causes trouble, the `p' -debug flag (*note Debug Levels::) can help isolate the problem. - - -File: m4.info, Node: Diversions, Next: Text handling, Prev: File Inclusion, Up: Top - -10 Diverting and undiverting output -*********************************** - -Diversions are a way of temporarily saving output. The output of `m4' -can at any time be diverted to a temporary file, and be reinserted into -the output stream, "undiverted", again at a later time. - - Numbered diversions are counted from 0 upwards, diversion number 0 -being the normal output stream. The number of simultaneous diversions -is limited mainly by the memory used to describe them, because GNU `m4' -tries to keep diversions in memory. However, there is a limit to the -overall memory usable by all diversions taken altogether (512K, -currently). When this maximum is about to be exceeded, a temporary -file is opened to receive the contents of the biggest diversion still -in memory, freeing this memory for other diversions. When creating the -temporary file, `m4' honors the value of the environment variable -`TMPDIR', and falls back to `/tmp'. So, it is theoretically possible -that the number and aggregate size of diversions is limited only by -available disk space. - - Diversions make it possible to generate output in a different order -than the input was read. It is possible to implement topological -sorting dependencies. For example, GNU Autoconf makes use of -diversions under the hood to ensure that the expansion of a prerequisite -macro appears in the output prior to the expansion of a dependent macro, -regardless of which order the two macros were invoked in the user's -input file. - -* Menu: - -* Divert:: Diverting output -* Undivert:: Undiverting output -* Divnum:: Diversion numbers -* Cleardivert:: Discarding diverted text - - -File: m4.info, Node: Divert, Next: Undivert, Up: Diversions - -10.1 Diverting output -===================== - -Output is diverted using `divert': - - -- Builtin: divert ([NUMBER = `0']) - The current diversion is changed to NUMBER. If NUMBER is left out - or empty, it is assumed to be zero. If NUMBER cannot be parsed, - the diversion is unchanged. - - The expansion of `divert' is void. - - When all the `m4' input will have been processed, all existing -diversions are automatically undiverted, in numerical order. - - divert(`1') - This text is diverted. - divert - => - This text is not diverted. - =>This text is not diverted. - ^D - => - =>This text is diverted. - - Several calls of `divert' with the same argument do not overwrite -the previous diverted text, but append to it. Diversions are printed -after any wrapped text is expanded. - - define(`text', `TEXT') - => - divert(`1')`diverted text.' - divert - => - m4wrap(`Wrapped text preceeds ') - => - ^D - =>Wrapped TEXT preceeds diverted text. - - If output is diverted to a negative diversion, it is simply -discarded. This can be used to suppress unwanted output. A common -example of unwanted output is the trailing newlines after macro -definitions. Here is a common programming idiom in `m4' for avoiding -them. - - divert(`-1') - define(`foo', `Macro `foo'.') - define(`bar', `Macro `bar'.') - divert - => - - Traditional implementations only supported ten diversions. But as a -GNU extension, diversion numbers can be as large as positive integers -will allow, rather than treating a multi-digit diversion number as a -request to discard text. - - divert(eval(`1<<28'))world - divert(`2')hello - ^D - =>hello - =>world - - Note that `divert' is an English word, but also an active macro -without arguments. When processing plain text, the word might appear in -normal text and be unintentionally swallowed as a macro invocation. One -way to avoid this is to use the `-P' option to rename all builtins -(*note Invoking m4: Operation modes.). Another is to write a wrapper -that requires a parameter to be recognized. - - We decided to divert the stream for irrigation. - =>We decided to the stream for irrigation. - define(`divert', `ifelse(`$#', `0', ``$0'', `builtin(`$0', $@)')') - => - divert(`-1') - Ignored text. - divert(`0') - => - We decided to divert the stream for irrigation. - =>We decided to divert the stream for irrigation. - - -File: m4.info, Node: Undivert, Next: Divnum, Prev: Divert, Up: Diversions - -10.2 Undiverting output -======================= - -Diverted text can be undiverted explicitly using the builtin `undivert': - - -- Builtin: undivert ([DIVERSIONS...]) - Undiverts the numeric DIVERSIONS given by the arguments, in the - order given. If no arguments are supplied, all diversions are - undiverted, in numerical order. - - As a GNU extension, DIVERSIONS may contain non-numeric strings, - which are treated as the names of files to copy into the output - without expansion. A warning is issued if a file could not be - opened. - - The expansion of `undivert' is void. - - divert(`1') - This text is diverted. - divert - => - This text is not diverted. - =>This text is not diverted. - undivert(`1') - => - =>This text is diverted. - => - - Notice the last two blank lines. One of them comes from the newline -following `undivert', the other from the newline that followed the -`divert'! A diversion often starts with a blank line like this. - - When diverted text is undiverted, it is _not_ reread by `m4', but -rather copied directly to the current output, and it is therefore not -an error to undivert into a diversion. Undiverting the empty string is -the same as specifying diversion 0; in either case nothing happens -since the output has already been flushed. - - divert(`1')diverted text - divert - => - undivert() - => - undivert(`0') - => - undivert - =>diverted text - => - - When a diversion has been undiverted, the diverted text is discarded, -and it is not possible to bring back diverted text more than once. - - divert(`1') - This text is diverted first. - divert(`0')undivert(`1')dnl - => - =>This text is diverted first. - undivert(`1') - => - divert(`1') - This text is also diverted but not appended. - divert(`0')undivert(`1')dnl - => - =>This text is also diverted but not appended. - - Attempts to undivert the current diversion are silently ignored. -Thus, when the current diversion is not 0, the current diversion does -not get rearranged among the other diversions. - - divert(`1')one - divert(`2')two - divert(`3')three - divert(`2')undivert`'dnl - divert`'undivert`'dnl - =>two - =>one - =>three - - GNU `m4' allows named files to be undiverted. Given a non-numeric -argument, the contents of the file named will be copied, uninterpreted, -to the current output. This complements the builtin `include' (*note -Include::). To illustrate the difference, the file -`m4-1.4.8/examples/foo' contains the word `bar': - - define(`bar', `BAR') - => - undivert(`foo') - =>bar - => - include(`foo') - =>BAR - => - - If the file is not found (or cannot be read), an error message is -issued, and the expansion is void. - - -File: m4.info, Node: Divnum, Next: Cleardivert, Prev: Undivert, Up: Diversions - -10.3 Diversion numbers -====================== - -The current diversion is tracked by the builtin `divnum': - - -- Builtin: divnum - Expands to the number of the current diversion. - - Initial divnum - =>Initial 0 - divert(`1') - Diversion one: divnum - divert(`2') - Diversion two: divnum - ^D - => - =>Diversion one: 1 - => - =>Diversion two: 2 - - -File: m4.info, Node: Cleardivert, Prev: Divnum, Up: Diversions - -10.4 Discarding diverted text -============================= - -Often it is not known, when output is diverted, whether the diverted -text is actually needed. Since all non-empty diversion are brought back -on the main output stream when the end of input is seen, a method of -discarding a diversion is needed. If all diversions should be -discarded, the easiest is to end the input to `m4' with `divert(`-1')' -followed by an explicit `undivert': - - divert(`1') - Diversion one: divnum - divert(`2') - Diversion two: divnum - divert(`-1') - undivert - ^D - -No output is produced at all. - - Clearing selected diversions can be done with the following macro: - - -- Composite: cleardivert ([DIVERSIONS...]) - Discard the contents of each of the listed numeric DIVERSIONS. - - define(`cleardivert', - `pushdef(`_n', divnum)divert(`-1')undivert($@)divert(_n)popdef(`_n')') - => - - It is called just like `undivert', but the effect is to clear the -diversions, given by the arguments. (This macro has a nasty bug! You -should try to see if you can find it and correct it; or *note Answers: -Improved cleardivert.). - - -File: m4.info, Node: Text handling, Next: Arithmetic, Prev: Diversions, Up: Top - -11 Macros for text handling -*************************** - -There are a number of builtins in `m4' for manipulating text in various -ways, extracting substrings, searching, substituting, and so on. - -* Menu: - -* Len:: Calculating length of strings -* Index macro:: Searching for substrings -* Regexp:: Searching for regular expressions -* Substr:: Extracting substrings -* Translit:: Translating characters -* Patsubst:: Substituting text by regular expression -* Format:: Formatting strings (printf-like) - - -File: m4.info, Node: Len, Next: Index macro, Up: Text handling - -11.1 Calculating length of strings -================================== - -The length of a string can be calculated by `len': - - -- Builtin: len (STRING) - Expands to the length of STRING, as a decimal number. - - The macro `len' is recognized only with parameters. - - len() - =>0 - len(`abcdef') - =>6 - - -File: m4.info, Node: Index macro, Next: Regexp, Prev: Len, Up: Text handling - -11.2 Searching for substrings -============================= - -Searching for substrings is done with `index': - - -- Builtin: index (STRING, SUBSTRING) - Expands to the index of the first occurrence of SUBSTRING in - STRING. The first character in STRING has index 0. If SUBSTRING - does not occur in STRING, `index' expands to `-1'. - - The macro `index' is recognized only with parameters. - - index(`gnus, gnats, and armadillos', `nat') - =>7 - index(`gnus, gnats, and armadillos', `dag') - =>-1 - - Omitting SUBSTRING evokes a warning, but still produces output. - - index(`abc') - error-->m4:stdin:1: Warning: too few arguments to builtin `index' - =>0 - - -File: m4.info, Node: Regexp, Next: Substr, Prev: Index macro, Up: Text handling - -11.3 Searching for regular expressions -====================================== - -Searching for regular expressions is done with the builtin `regexp': - - -- Builtin: regexp (STRING, REGEXP, [REPLACEMENT]) - Searches for REGEXP in STRING. The syntax for regular expressions - is the same as in GNU Emacs. *Note Syntax of Regular Expressions: - (emacs)Regexps. - - If REPLACEMENT is omitted, `regexp' expands to the index of the - first match of REGEXP in STRING. If REGEXP does not match - anywhere in STRING, it expands to -1. - - If REPLACEMENT is supplied, and there was a match, `regexp' - changes the expansion to this argument, with `\N' substituted by - the text matched by the Nth parenthesized sub-expression of - REGEXP, up to nine sub-expressions. The escape `\&' is replaced - by the text of the entire regular expression matched. For all - other characters, `\' treats the next character literally. A - warning is issued if there were fewer sub-expressions than the - `\N' requested, or if there is a trailing `\'. If there was no - match, `regexp' expands to the empty string. - - The macro `regexp' is recognized only with parameters. - - regexp(`GNUs not Unix', `\<[a-z]\w+') - =>5 - regexp(`GNUs not Unix', `\-1 - regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') - =>*** Unix *** nix *** - regexp(`GNUs not Unix', `\ - - Here are some more examples on the handling of backslash: - - regexp(`abc', `\(b\)', `\\\10\a') - =>\b0a - regexp(`abc', `b', `\1\') - error-->m4:stdin:2: Warning: sub-expression 1 not present - error-->m4:stdin:2: Warning: trailing \ ignored in replacement - => - regexp(`abc', `\(\(d\)?\)\(c\)', `\1\2\3\4\5\6') - error-->m4:stdin:3: Warning: sub-expression 4 not present - error-->m4:stdin:3: Warning: sub-expression 5 not present - error-->m4:stdin:3: Warning: sub-expression 6 not present - =>c - - Omitting REGEXP evokes a warning, but still produces output. - - regexp(`abc') - error-->m4:stdin:1: Warning: too few arguments to builtin `regexp' - =>0 - - -File: m4.info, Node: Substr, Next: Translit, Prev: Regexp, Up: Text handling - -11.4 Extracting substrings -========================== - -Substrings are extracted with `substr': - - -- Builtin: substr (STRING, FROM, [LENGTH]) - Expands to the substring of STRING, which starts at index FROM, - and extends for LENGTH characters, or to the end of STRING, if - LENGTH is omitted. The starting index of a string is always 0. - The expansion is empty if there is an error parsing FROM or - LENGTH, if FROM is beyond the end of STRING, or if LENGTH is - negative. - - The macro `substr' is recognized only with parameters. - - substr(`gnus, gnats, and armadillos', `6') - =>gnats, and armadillos - substr(`gnus, gnats, and armadillos', `6', `5') - =>gnats - - Omitting FROM evokes a warning, but still produces output. - - substr(`abc') - error-->m4:stdin:1: Warning: too few arguments to builtin `substr' - =>abc - substr(`abc',) - error-->m4:stdin:2: empty string treated as 0 in builtin `substr' - =>abc - - -File: m4.info, Node: Translit, Next: Patsubst, Prev: Substr, Up: Text handling - -11.5 Translating characters -=========================== - -Character translation is done with `translit': - - -- Builtin: translit (STRING, CHARS, [REPLACEMENT]) - Expands to STRING, with each character that occurs in CHARS - translated into the character from REPLACEMENT with the same index. - - If REPLACEMENT is shorter than CHARS, the excess characters of - CHARS are deleted from the expansion; if CHARS is shorter, the - excess characters in REPLACEMENT are silently ignored. If - REPLACEMENT is omitted, all characters in STRING that are present - in CHARS are deleted from the expansion. If a character appears - more than once in CHARS, only the first instance is used in making - the translation. Only a single translation pass is made, even if - characters in REPLACEMENT also appear in CHARS. - - As a GNU extension, both CHARS and REPLACEMENT can contain - character-ranges, e.g., `a-z' (meaning all lowercase letters) or - `0-9' (meaning all digits). To include a dash `-' in CHARS or - REPLACEMENT, place it first or last in the entire string, or as - the last character of a range. Back-to-back ranges can share a - common endpoint. It is not an error for the last character in the - range to be `larger' than the first. In that case, the range runs - backwards, i.e., `9-0' means the string `9876543210'. The - expansion of a range is dependent on the underlying encoding of - characters, so using ranges is not always portable between - machines. - - The macro `translit' is recognized only with parameters. - - translit(`GNUs not Unix', `A-Z') - =>s not nix - translit(`GNUs not Unix', `a-z', `A-Z') - =>GNUS NOT UNIX - translit(`GNUs not Unix', `A-Z', `z-a') - =>tmfs not fnix - translit(`+,-12345', `+--1-5', `<;>a-c-a') - =><;>abcba - translit(`abcdef', `aabdef', `bcged') - =>bgced - - In the ASCII encoding, the first example deletes all uppercase -letters, the second converts lowercase to uppercase, and the third -`mirrors' all uppercase letters, while converting them to lowercase. -The two first cases are by far the most common, even though they are not -portable to EBCDIC or other encodings. The fourth example shows a -range ending in `-', as well as back-to-back ranges. The final example -shows that `a' is mapped to `b', not `c'; the resulting `b' is not -further remapped to `g'; the `d' and `e' are swapped, and the `f' is -discarded. - - Omitting CHARS evokes a warning, but still produces output. - - translit(`abc') - error-->m4:stdin:1: Warning: too few arguments to builtin `translit' - =>abc - - -File: m4.info, Node: Patsubst, Next: Format, Prev: Translit, Up: Text handling - -11.6 Substituting text by regular expression -============================================ - -Global substitution in a string is done by `patsubst': - - -- Builtin: patsubst (STRING, REGEXP, [REPLACEMENT]) - Searches STRING for matches of REGEXP, and substitutes REPLACEMENT - for each match. The syntax for regular expressions is the same as - in GNU Emacs (*note Regexp::). - - The parts of STRING that are not covered by any match of REGEXP - are copied to the expansion. Whenever a match is found, the - search proceeds from the end of the match, so a character from - STRING will never be substituted twice. If REGEXP matches a - string of zero length, the start position for the search is - incremented, to avoid infinite loops. - - When a replacement is to be made, REPLACEMENT is inserted into the - expansion, with `\N' substituted by the text matched by the Nth - parenthesized sub-expression of PATSUBST, for up to nine - sub-expressions. The escape `\&' is replaced by the text of the - entire regular expression matched. For all other characters, `\' - treats the next character literally. A warning is issued if there - were fewer sub-expressions than the `\N' requested, or if there is - a trailing `\'. - - The REPLACEMENT argument can be omitted, in which case the text - matched by REGEXP is deleted. - - The macro `patsubst' is recognized only with parameters. - - patsubst(`GNUs not Unix', `^', `OBS: ') - =>OBS: GNUs not Unix - patsubst(`GNUs not Unix', `\<', `OBS: ') - =>OBS: GNUs OBS: not OBS: Unix - patsubst(`GNUs not Unix', `\w*', `(\&)') - =>(GNUs)() (not)() (Unix)() - patsubst(`GNUs not Unix', `\w+', `(\&)') - =>(GNUs) (not) (Unix) - patsubst(`GNUs not Unix', `[A-Z][a-z]+') - =>GN not - patsubst(`GNUs not Unix', `not', `NOT\') - error-->m4:stdin:6: Warning: trailing \ ignored in replacement - =>GNUs NOT Unix - - Here is a slightly more realistic example, which capitalizes -individual word or whole sentences, by substituting calls of the macros -`upcase' and `downcase' into the strings. - - -- Composite: upcase (TEXT) - -- Composite: downcase (TEXT) - -- Composite: capitalize (TEXT) - Expand to TEXT, but with capitalization changed: `upcase' changes - all letters to upper case, `downcase' changes all letters to lower - case, and `capitalize' changes the first character of each word to - upper case and the remaining characters to lower case. - - define(`upcase', `translit(`$*', `a-z', `A-Z')')dnl - define(`downcase', `translit(`$*', `A-Z', `a-z')')dnl - define(`capitalize1', - `regexp(`$1', `^\(\w\)\(\w*\)', - `upcase(`\1')`'downcase(`\2')')')dnl - define(`capitalize', - `patsubst(`$1', `\w+', `capitalize1(`\&')')')dnl - capitalize(`GNUs not Unix') - =>Gnus Not Unix - - While `regexp' replaces the whole input with the replacement as soon -as there is a match, `patsubst' replaces each _occurrence_ of a match -and preserves non-matching pieces: - - define(`patreg', - `patsubst($@) - regexp($@)')dnl - patreg(`bar foo baz Foo', `foo\|Foo', `FOO') - =>bar FOO baz FOO - =>FOO - patreg(`aba abb 121', `\(.\)\(.\)\1', `\2\1\2') - =>bab abb 212 - =>bab - - Omitting REGEXP evokes a warning, but still produces output. - - patsubst(`abc') - error-->m4:stdin:1: Warning: too few arguments to builtin `patsubst' - =>abc - - -File: m4.info, Node: Format, Prev: Patsubst, Up: Text handling - -11.7 Formatted output -===================== - -Formatted output can be made with `format': - - -- Builtin: format (FORMAT-STRING, ...) - Works much like the C function `printf'. The first argument - FORMAT-STRING can contain `%' specifications which are satisfied - by additional arguments, and the expansion of `format' is the - formatted string. - - The macro `format' is recognized only with parameters. - - Its use is best described by a few examples: - - define(`foo', `The brown fox jumped over the lazy dog') - => - format(`The string "%s" uses %d characters', foo, len(foo)) - =>The string "The brown fox jumped over the lazy dog" uses 38 characters - format(`%.0f', `56789.9876') - =>56790 - len(format(`%-*X', `300', `1')) - =>300 - - Using the `forloop' macro defined earlier (*note Forloop::), this -example shows how `format' can be used to produce tabular output. - - include(`forloop.m4') - => - forloop(`i', `1', `10', `format(`%6d squared is %10d - ', i, eval(i**2))') - => 1 squared is 1 - => 2 squared is 4 - => 3 squared is 9 - => 4 squared is 16 - => 5 squared is 25 - => 6 squared is 36 - => 7 squared is 49 - => 8 squared is 64 - => 9 squared is 81 - => 10 squared is 100 - => - - The builtin `format' is modeled after the ANSI C `printf' function, -and supports these `%' specifiers: `c', `s', `d', `o', `x', `X', `u', -`e', `E', `f', `F', `g', `G', and `%'; it supports field widths and -precisions, and the modifiers `+', `-', ` ', `0', `#', `h' and `l'. -For more details on the functioning of `printf', see the C Library -Manual. - - For now, unrecognized specifiers are silently ignored, but it is -anticipated that a future release of GNU `m4' will support more -specifiers, and give warnings when problems are encountered. Likewise, -escape sequences are not yet recognized. - - -File: m4.info, Node: Arithmetic, Next: Shell commands, Prev: Text handling, Up: Top - -12 Macros for doing arithmetic -****************************** - -Integer arithmetic is included in `m4', with a C-like syntax. As -convenient shorthands, there are builtins for simple increment and -decrement operations. - -* Menu: - -* Incr:: Decrement and increment operators -* Eval:: Evaluating integer expressions - - -File: m4.info, Node: Incr, Next: Eval, Up: Arithmetic - -12.1 Decrement and increment operators -====================================== - -Increment and decrement of integers are supported using the builtins -`incr' and `decr': - - -- Builtin: incr (NUMBER) - -- Builtin: decr (NUMBER) - Expand to the numerical value of NUMBER, incremented or - decremented, respectively, by one. Except for the empty string, - the expansion is empty if NUMBER could not be parsed. - - The macros `incr' and `decr' are recognized only with parameters. - - incr(`4') - =>5 - decr(`7') - =>6 - incr() - error-->m4:stdin:3: empty string treated as 0 in builtin `incr' - =>1 - decr() - error-->m4:stdin:4: empty string treated as 0 in builtin `decr' - =>-1 - - -File: m4.info, Node: Eval, Prev: Incr, Up: Arithmetic - -12.2 Evaluating integer expressions -=================================== - -Integer expressions are evaluated with `eval': - - -- Builtin: eval (EXPRESSION, [RADIX = `10'], [WIDTH]) - Expands to the value of EXPRESSION. The expansion is empty if an - error is encountered while parsing the arguments. If specified, - RADIX and WIDTH control the format of the output. - - The macro `eval' is recognized only with parameters. - - Expressions can contain the following operators, listed in order of -decreasing precedence. - -`+ -' - Unary plus and minus - -`**' - Exponentiation - -`* / %' - Multiplication, division and modulo - -`+ -' - Addition and subtraction - -`<< >>' - Shift left or right - -`== != > >= < <=' - Relational operators - -`!' - Logical negation - -`~' - Bitwise negation - -`&' - Bitwise and - -`^' - Bitwise exclusive-or - -`|' - Bitwise or - -`&&' - Logical and - -`||' - Logical or - - All operators, except exponentiation, are left associative. - - Note that some older `m4' implementations use `^' as an alternate -operator for exponentiation, although POSIX requires the C behavior of -bitwise exclusive-or. On the other hand, the precedence of `~' and `!' -are different in GNU `m4' than they are in C, matching the precedence -in traditional `m4' implementations. This behavior is likely to change -in a future version to match POSIX, so use parentheses to force the -desired precedence. - - Within EXPRESSION, (but not RADIX or WIDTH), numbers without a -special prefix are decimal. A simple `0' prefix introduces an octal -number. `0x' introduces a hexadecimal number. `0b' introduces a -binary number. `0r' introduces a number expressed in any radix between -1 and 36: the prefix should be immediately followed by the decimal -expression of the radix, a colon, then the digits making the number. -For radix 1, leading zeros are ignored and all remaining digits must be -`1'; for all other radices, the digits are `0', `1', `2', .... Beyond -`9', the digits are `a', `b' ... up to `z'. Lower and upper case -letters can be used interchangeably in numbers prefixes and as number -digits. - - Parentheses may be used to group subexpressions whenever needed. -For the relational operators, a true relation returns `1', and a false -relation return `0'. - - Here are a few examples of use of `eval'. - - eval(`-3 * 5') - =>-15 - eval(index(`Hello world', `llo') >= 0) - =>1 - eval(`0r1:0111 + 0b100 + 0r3:12') - =>12 - define(`square', `eval(`('$1`)**2')') - => - square(`9') - =>81 - square(square(`5')`+1') - =>676 - define(`foo', `666') - => - eval(`foo/6') - error-->m4:stdin:8: bad expression in eval: foo/6 - => - eval(foo/6) - =>111 - - As the last two lines show, `eval' does not handle macro names, even -if they expand to a valid expression (or part of a valid expression). -Therefore all macros must be expanded before they are passed to `eval'. - - All evaluation is done with 32-bit signed integers, assuming -2's-complement with wrap-around. The shift operators are defined in GNU -`m4' by doing an implicit bit-wise and of the right-hand operand with -0x1f, and sign-extension with right shift. - - eval(0x80000000 / -1) - =>-2147483648 - eval(0x80000000 % -1) - =>0 - eval(0x7fffffff) - =>2147483647 - incr(eval(0x7fffffff)) - =>-2147483648 - eval(-4 >> 33) - =>-2 - - If RADIX is specified, it specifies the radix to be used in the -expansion. The default radix is 10; this is also the case if RADIX is -the empty string. It is an error if the radix is outside the range of -1 through 36, inclusive. The result of `eval' is always taken to be -signed. No radix prefix is output, and for radices greater than 10, -the digits are lower case. The WIDTH argument specifies the minimum -output width, excluding any negative sign. The result is zero-padded -to extend the expansion to the requested width. It is an error if the -width is negative. On error, the expansion of `eval' is empty. - - eval(`666', `10') - =>666 - eval(`666', `11') - =>556 - eval(`666', `6') - =>3030 - eval(`666', `6', `10') - =>0000003030 - eval(`-666', `6', `10') - =>-0000003030 - eval(`10', `', `0') - =>10 - `0r1:'eval(`10', `1', `11') - =>0r1:01111111111 - eval(`10', `16') - =>a - - -File: m4.info, Node: Shell commands, Next: Miscellaneous, Prev: Arithmetic, Up: Top - -13 Macros for running shell commands -************************************ - -There are a few builtin macros in `m4' that allow you to run shell -commands from within `m4'. - - Note that the definition of a valid shell command is system -dependent. On UNIX systems, this is the typical `/bin/sh'. But on -other systems, such as native Windows, the shell has a different syntax -of commands that it understands. Some examples in this chapter assume -`/bin/sh', and also demonstrate how to quit early with a known exit -value if this is not the case. - -* Menu: - -* Platform macros:: Determining the platform -* Syscmd:: Executing simple commands -* Esyscmd:: Reading the output of commands -* Sysval:: Exit status -* Mkstemp:: Making temporary files - - -File: m4.info, Node: Platform macros, Next: Syscmd, Up: Shell commands - -13.1 Determining the platform -============================= - -Sometimes it is desirable for an input file to know which platform `m4' -is running on. GNU `m4' provides several macros that are predefined to -expand to the empty string; checking for their existence will confirm -platform details. - - -- Optional builtin: __gnu__ - -- Optional builtin: __os2__ - -- Optional builtin: os2 - -- Optional builtin: __unix__ - -- Optional builtin: unix - -- Optional builtin: __windows__ - -- Optional builtin: windows - Each of these macros is conditionally defined as needed to - describe the environment of `m4'. If defined, each macro expands - to the empty string. - - When GNU extensions are in effect (that is, when you did not use the -`-G' option, *note Invoking m4: Limits control.), GNU `m4' will define -the macro `__gnu__' to expand to the empty string. - - __gnu__ - => - ifdef(`__gnu__', `Extensions are active') - =>Extensions are active - - On UNIX systems, GNU `m4' will define `__unix__' by default, or -`unix' when the `-G' option is specified. - - On native Windows systems, GNU `m4' will define `__windows__' by -default, or `windows' when the `-G' option is specified. - - On OS/2 systems, GNU `m4' will define `__os2__' by default, or `os2' -when the `-G' option is specified. - - If GNU `m4' does not provide a platform macro for your system, -please report that as a bug. - - define(`provided', `0') - => - ifdef(`__unix__', `define(`provided', incr(provided))') - => - ifdef(`__windows__', `define(`provided', incr(provided))') - => - ifdef(`__os2__', `define(`provided', incr(provided))') - => - provided - =>1 - - -File: m4.info, Node: Syscmd, Next: Esyscmd, Prev: Platform macros, Up: Shell commands - -13.2 Executing simple commands -============================== - -Any shell command can be executed, using `syscmd': - - -- Builtin: syscmd (SHELL-COMMAND) - Executes SHELL-COMMAND as a shell command. - - The expansion of `syscmd' is void, _not_ the output from - SHELL-COMMAND! Output or error messages from SHELL-COMMAND are - not read by `m4'. *Note Esyscmd::, if you need to process the - command output. - - Prior to executing the command, `m4' flushes its buffers. The - default standard input, output and error of SHELL-COMMAND are the - same as those of `m4'. - - The macro `syscmd' is recognized only with parameters. - - define(`foo', `FOO') - => - syscmd(`echo foo') - =>foo - => - - Note how the expansion of `syscmd' keeps the trailing newline of the -command, as well as using the newline that appeared after the macro. - - As an example of SHELL-COMMAND using the same standard input as -`m4', the command line `echo "m4wrap(\`syscmd(\`cat')')" | m4' will -tell `m4' to read all of its input before executing the wrapped text, -then hand a valid (albeit emptied) pipe as standard input for the `cat' -subcommand. Therefore, you should be careful when using standard input -(either by specifying no files, or by passing `-' as a file name on the -command line, *note Invoking m4: Command line files.), and also -invoking subcommands via `syscmd' or `esyscmd' that consume data from -standard input. When standard input is a seekable file, the subprocess -will pick up with the next character not yet processed by `m4'; when it -is a pipe or other non-seekable file, there is no guarantee how much -data will already be buffered by `m4' and thus unavailable to the child. - - -File: m4.info, Node: Esyscmd, Next: Sysval, Prev: Syscmd, Up: Shell commands - -13.3 Reading the output of commands -=================================== - -If you want `m4' to read the output of a shell command, use `esyscmd': - - -- Builtin: esyscmd (SHELL-COMMAND) - Expands to the standard output of the shell command SHELL-COMMAND. - - Prior to executing the command, `m4' flushes its buffers. The - default standard input and standard error of SHELL-COMMAND are the - same as those of `m4'. The error output of SHELL-COMMAND is not a - part of the expansion: it will appear along with the error output - of `m4'. - - The macro `esyscmd' is recognized only with parameters. - - define(`foo', `FOO') - => - esyscmd(`echo foo') - =>FOO - => - - Note how the expansion of `esyscmd' keeps the trailing newline of -the command, as well as using the newline that appeared after the macro. - - Just as with `syscmd', care must be exercised when sharing standard -input between `m4' and the child process of `esyscmd'. - - -File: m4.info, Node: Sysval, Next: Mkstemp, Prev: Esyscmd, Up: Shell commands - -13.4 Exit status -================ - -To see whether a shell command succeeded, use `sysval': - - -- Builtin: sysval - Expands to the exit status of the last shell command run with - `syscmd' or `esyscmd'. Expands to 0 if no command has been run - yet. - - syscmd(`false') - => - ifelse(sysval, `0', `zero', `non-zero') - =>non-zero - syscmd(`exit 2') - => - sysval - =>2 - syscmd(`true') - => - sysval - =>0 - esyscmd(`false') - => - ifelse(sysval, `0', `zero', `non-zero') - =>non-zero - esyscmd(`exit 2') - => - sysval - =>2 - esyscmd(`true') - => - sysval - =>0 - - `sysval' results in 127 if there was a problem executing the -command, for example, if the system-imposed argument length is exceeded, -or if there were not enough resources to fork. It is not possible to -distinguish between failed execution and successful execution that had -an exit status of 127. - - On UNIX platforms, where it is possible to detect when command -execution is terminated by a signal, rather than a normal exit, the -result is the signal number shifted left by eight bits. - - dnl This test assumes kill is a shell builtin, and that signals are - dnl recognizable. - ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics - ')m4exit(`77')')dnl - syscmd(`kill -13 $$') - => - sysval - =>3328 - esyscmd(`kill -9 $$') - => - sysval - =>2304 - - -File: m4.info, Node: Mkstemp, Prev: Sysval, Up: Shell commands - -13.5 Making temporary files -=========================== - -Commands specified to `syscmd' or `esyscmd' might need a temporary -file, for output or for some other purpose. There is a builtin macro, -`mkstemp', for making a temporary file: - - -- Builtin: mkstemp (TEMPLATE) - -- Builtin: maketemp (TEMPLATE) - Expands to a name of a new, empty file, made from the string - TEMPLATE, which should end with the string `XXXXXX'. The six `X' - characters are then replaced with random characters matching the - regular expression `[a-zA-Z0-9._-]', in order to make the file - name unique. If fewer than six `X' characters are found at the end - of `template', the result will be longer than the template. The - created file will have access permissions as if by `chmod =rw,go=', - meaning that the current umask of the `m4' process is taken into - account, and at most only the current user can read and write the - file. - - The traditional behavior, standardized by POSIX, is that - `maketemp' merely replaces the trailing `X' with the process id, - without creating a file, and without ensuring that the resulting - string is a unique file name. In part, this means that using the - same TEMPLATE twice in the same input file will result in the same - expansion. This behavior is a security hole, as it is very easy - for another process to guess the name that will be generated, and - thus interfere with a subsequent use of `syscmd' trying to - manipulate that file name. Hence, POSIX has recommended that all - new implementations of `m4' provide the secure `mkstemp' builtin, - and that users of `m4' check for its existence. - - The macros `mkstemp' and `maketemp' are recognized only with - parameters. - - If you try this next example, you will most likely get different -output for the two file names, since the replacement characters are -randomly chosen: - - maketemp(`/tmp/fooXXXXXX') - =>/tmp/fooa07346 - ifdef(`mkstemp', `define(`maketemp', defn(`mkstemp'))', - `define(`mkstemp', defn(`maketemp'))dnl - errprint(`warning: potentially insecure maketemp implementation - ')') - => - mkstemp(`doc') - =>docQv83Uw - - Unless you use the `--traditional' command line option (or `-G', -*note Invoking m4: Limits control.), the GNU version of `maketemp' is -secure. This means that using the same template to multiple calls will -generate multiple files. However, we recommend that you use the new -`mkstemp' macro, introduced in GNU M4 1.4.8, which is secure even in -traditional mode. - - syscmd(`echo foo??????')dnl - =>foo?????? - define(`file1', maketemp(`fooXXXXXX'))dnl - ifelse(esyscmd(`echo foo??????'), `foo??????', `no file', `created') - =>created - define(`file2', maketemp(`fooXX'))dnl - define(`file3', mkstemp(`fooXXXXXX'))dnl - ifelse(len(file1), len(file2), `same length', `different') - =>same length - ifelse(file1, file2, `same', `different file') - =>different file - ifelse(file2, file3, `same', `different file') - =>different file - ifelse(file1, file3, `same', `different file') - =>different file - syscmd(`rm 'file1 file2 file3) - => - sysval - =>0 - - -File: m4.info, Node: Miscellaneous, Next: Frozen files, Prev: Shell commands, Up: Top - -14 Miscellaneous builtin macros -******************************* - -This chapter describes various builtins, that do not really belong in -any of the previous chapters. - -* Menu: - -* Errprint:: Printing error messages -* Location:: Printing current location -* M4exit:: Exiting from `m4' - - -File: m4.info, Node: Errprint, Next: Location, Up: Miscellaneous - -14.1 Printing error messages -============================ - -You can print error messages using `errprint': - - -- Builtin: errprint (MESSAGE, ...) - Prints MESSAGE and the rest of the arguments to standard error, - separated by spaces. Standard error is used, regardless of the - `--debugfile' option (*note Invoking m4: Debugging options.). - - The expansion of `errprint' is void. The macro `errprint' is - recognized only with parameters. - - errprint(`Invalid arguments to forloop - ') - error-->Invalid arguments to forloop - => - errprint(`1')errprint(`2',`3 - ') - error-->12 3 - => - - A trailing newline is _not_ printed automatically, so it should be -supplied as part of the argument, as in the example. Unfortunately, the -exact output of `errprint' is not very portable to other `m4' -implementations: POSIX requires that all arguments be printed, but some -implementations of `m4' only print the first. Furthermore, some BSD -implementations always append a newline for each `errprint' call, -regardless of whether the last argument already had one, and POSIX is -silent on whether this is acceptable. - - -File: m4.info, Node: Location, Next: M4exit, Prev: Errprint, Up: Miscellaneous - -14.2 Printing current location -============================== - -To make it possible to specify the location of an error, three utility -builtins exist: - - -- Builtin: __file__ - -- Builtin: __line__ - -- Builtin: __program__ - Expand to the quoted name of the current input file, the current - input line number in that file, and the quoted name of the current - invocation of `m4'. - - errprint(__program__:__file__:__line__: `input error - ') - error-->m4:stdin:1: input error - => - - Line numbers start at 1 for each file. If the file was found due to -the `-I' option or `M4PATH' environment variable, that is reflected in -the file name. The syncline option (`-s', *note Invoking m4: -Preprocessor features.), and the `f' and `l' flags of `debugmode' -(*note Debug Levels::), also use this notion of current file and line. -Redefining the three location macros has no effect on syncline, debug, -or warning message output. Assume this example is run in the -`m4-1.4.8/checks' directory of the GNU M4 package, using -`--include=../examples' in the command line to find the file `incl.m4' -mentioned earlier: - - define(`foo', ``$0' called at __file__:__line__') - => - foo - =>foo called at stdin:2 - include(`incl.m4') - =>Include file start - =>foo called at ../examples/incl.m4:2 - =>Include file end - => - - The location of macros invoked during the rescanning of macro -expansion text corresponds to the location in the file where the -expansion was triggered, regardless of how many newline characters the -expansion text contains. As of GNU M4 1.4.8, the location of text -wrapped with `m4wrap' (*note M4wrap::) is the point at which the -`m4wrap' was invoked. Previous versions, however, behaved as though -wrapped text came from line 0 of the file "". - - define(`echo', `$@') - => - define(`foo', `echo(__line__ - __line__)') - => - echo(__line__ - __line__) - =>4 - =>5 - m4wrap(`foo - ') - => - foo(errprint(__line__ - __line__ - )) - error-->8 - error-->9 - =>8 - =>8 - __line__ - =>11 - ^D - =>6 - =>6 - - The `__program__' macro behaves like `$0' in shell terminology. If -you invoke `m4' through an absolute path or a link with a different -spelling, rather than by relying on a `PATH' search for plain `m4', it -will affect how `__program__' expands. The intent is that you can use -it to produce error messages with the same formatting that `m4' -produces internally. It can also be used within `syscmd' (*note -Syscmd::) to pick the same version of `m4' that is currently running, -rather than whatever version of `m4' happens to be first in `PATH'. It -was first introduced in GNU M4 1.4.6. - - -File: m4.info, Node: M4exit, Prev: Location, Up: Miscellaneous - -14.3 Exiting from `m4' -====================== - -If you need to exit from `m4' before the entire input has been read, -you can use `m4exit': - - -- Builtin: m4exit ([CODE = `0']) - Causes `m4' to exit, with exit status CODE. If CODE is left out, - the exit status is zero. If CODE cannot be parsed, or is outside - the range of 0 to 255, the exit status is one. No further input - is read, and all wrapped and diverted text is discarded. - - m4wrap(`This text is lost due to `m4exit'.') - => - divert(`1') So is this. - divert - => - m4exit And this is never read. - - A common use of this is to abort processing: - - -- Composite: fatal_error (MESSAGE) - Abort processing with an error message and non-zero status. Prefix - MESSAGE with details about where the error occurred, and print the - resulting string to standard error. - - define(`fatal_error', - `errprint(__program__:__file__:__line__`: fatal error: $* - ')m4exit(`1')') - => - fatal_error(`this is a BAD one, buster') - error-->m4:stdin:4: fatal error: this is a BAD one, buster - - After this macro call, `m4' will exit with exit status 1. This macro -is only intended for error exits, since the normal exit procedures are -not followed, e.g., diverted text is not undiverted, and saved text -(*note M4wrap::) is not reread. (This macro could be made more robust -to earlier versions of `m4'. You should try to see if you can find -weaknesses and correct them; or *note Answers: Improved fatal_error.). - - Note that it is still possible for the exit status to be different -than what was requested by `m4exit'. If `m4' detects some other error, -such as a write error on standard output, the exit status will be -non-zero even if `m4exit' requested zero. - - If standard input is seekable, then the file will be positioned at -the next unread character. If it is a pipe or other non-seekable file, -then there are no guarantees how much data `m4' might have read into -buffers, and thus discarded. - - -File: m4.info, Node: Frozen files, Next: Compatibility, Prev: Miscellaneous, Up: Top - -15 Fast loading of frozen state -******************************* - -Some bigger `m4' applications may be built over a common base -containing hundreds of definitions and other costly initializations. -Usually, the common base is kept in one or more declarative files, -which files are listed on each `m4' invocation prior to the user's -input file, or else each input file uses `include'. - - Reading the common base of a big application, over and over again, -may be time consuming. GNU `m4' offers some machinery to speed up the -start of an application using lengthy common bases. - -* Menu: - -* Using frozen files:: Using frozen files -* Frozen file format:: Frozen file format - - -File: m4.info, Node: Using frozen files, Next: Frozen file format, Up: Frozen files - -15.1 Using frozen files -======================= - -Suppose a user has a library of `m4' initializations in `base.m4', -which is then used with multiple input files: - - m4 base.m4 input1.m4 - m4 base.m4 input2.m4 - m4 base.m4 input3.m4 - - Rather than spending time parsing the fixed contents of `base.m4' -every time, the user might rather execute: - - m4 -F base.m4f base.m4 - -once, and further execute, as often as needed: - - m4 -R base.m4f input1.m4 - m4 -R base.m4f input2.m4 - m4 -R base.m4f input3.m4 - -with the varying input. The first call, containing the `-F' option, -only reads and executes file `base.m4', defining various application -macros and computing other initializations. Once the input file -`base.m4' has been completely processed, GNU `m4' produces on -`base.m4f' a "frozen" file, that is, a file which contains a kind of -snapshot of the `m4' internal state. - - Later calls, containing the `-R' option, are able to reload the -internal state of `m4', from `base.m4f', _prior_ to reading any other -input files. This means instead of starting with a virgin copy of -`m4', input will be read after having effectively recovered the effect -of a prior run. In our example, the effect is the same as if file -`base.m4' has been read anew. However, this effect is achieved a lot -faster. - - Only one frozen file may be created or read in any one `m4' -invocation. It is not possible to recover two frozen files at once. -However, frozen files may be updated incrementally, through using `-R' -and `-F' options simultaneously. For example, if some care is taken, -the command: - - m4 file1.m4 file2.m4 file3.m4 file4.m4 - -could be broken down in the following sequence, accumulating the same -output: - - m4 -F file1.m4f file1.m4 - m4 -R file1.m4f -F file2.m4f file2.m4 - m4 -R file2.m4f -F file3.m4f file3.m4 - m4 -R file3.m4f file4.m4 - - Some care is necessary because not every effort has been made for -this to work in all cases. In particular, the trace attribute of -macros is not handled, nor the current setting of `changeword'. -Currently, `m4wrap' and `sysval' also have problems. Also, -interactions for some options of `m4', being used in one call and not -in the next, have not been fully analyzed yet. On the other end, you -may be confident that stacks of `pushdef' definitions are handled -correctly, as well as undefined or renamed builtins, and changed -strings for quotes or comments. And future releases of GNU M4 will -improve on the utility of frozen files. - - When an `m4' run is to be frozen, the automatic undiversion which -takes place at end of execution is inhibited. Instead, all positively -numbered diversions are saved into the frozen file. The active -diversion number is also transmitted. - - A frozen file to be reloaded need not reside in the current -directory. It is looked up the same way as an `include' file (*note -Search Path::). - - If the frozen file was generated with a newer version of `m4', and -contains directives that an older `m4' cannot parse, attempting to load -the frozen file with option `-R' will cause `m4' to exit with status 63 -to indicate version mismatch. - - -File: m4.info, Node: Frozen file format, Prev: Using frozen files, Up: Frozen files - -15.2 Frozen file format -======================= - -Frozen files are sharable across architectures. It is safe to write a -frozen file on one machine and read it on another, given that the -second machine uses the same or newer version of GNU `m4'. It is -conventional, but not required, to give a frozen file the suffix of -`.m4f'. - - These are simple (editable) text files, made up of directives, each -starting with a capital letter and ending with a newline (). -Wherever a directive is expected, the character `#' introduces a -comment line; empty lines are also ignored if they are not part of an -embedded string. In the following descriptions, each LEN refers to the -length of the corresponding strings STR in the next line of input. -Numbers are always expressed in decimal. There are no escape -characters. The directives are: - -`C LEN1 , LEN2 STR1 STR2 ' - Uses STR1 and STR2 as the begin-comment and end-comment strings. - If omitted, then `#' and are the comment delimiters. - -`D NUMBER, LEN STR ' - Selects diversion NUMBER, making it current, then copy STR in the - current diversion. NUMBER may be a negative number for a - non-existing diversion. To merely specify an active selection, - use this command with an empty STR. With 0 as the diversion - NUMBER, STR will be issued on standard output at reload time. GNU - `m4' will not produce the `D' directive with non-zero length for - diversion 0, but this can be done with manual edits. This - directive may appear more than once for the same diversion, in - which case the diversion is the concatenation of the various uses. - If omitted, then diversion 0 is current. - -`F LEN1 , LEN2 STR1 STR2 ' - Defines, through `pushdef', a definition for STR1 expanding to the - function whose builtin name is STR2. If the builtin does not - exist (for example, if the frozen file was produced by a copy of - `m4' compiled with changeword support, but the version of `m4' - reloading was compiled without it), the reload is silent, but any - subsequent use of the definition of STR1 will result in a warning. - This directive may appear more than once for the same name, and - its order, along with `T', is important. If omitted, you will - have no access to any builtins. - -`Q LEN1 , LEN2 STR1 STR2 ' - Uses STR1 and STR2 as the begin-quote and end-quote strings. If - omitted, then ``' and `'' are the quote delimiters. - -`T LEN1 , LEN2 STR1 STR2 ' - Defines, though `pushdef', a definition for STR1 expanding to the - text given by STR2. This directive may appear more than once for - the same name, and its order, along with `F', is important. - -`V NUMBER ' - Confirms the format of the file. `m4' 1.4.8 only creates and - understands frozen files where NUMBER is 1. This directive must - be the first non-comment in the file, and may not appear more than - once. - - -File: m4.info, Node: Compatibility, Next: Answers, Prev: Frozen files, Up: Top - -16 Compatibility with other versions of `m4' -******************************************** - -This chapter describes the differences between this implementation of -`m4', and the implementation found under UNIX, notably System V, -Release 3. - - There are also differences in BSD flavors of `m4'. No attempt is -made to summarize these here. - -* Menu: - -* Extensions:: Extensions in GNU M4 -* Incompatibilities:: Facilities in System V m4 not in GNU M4 -* Other Incompatibilities:: Other incompatibilities - - -File: m4.info, Node: Extensions, Next: Incompatibilities, Up: Compatibility - -16.1 Extensions in GNU `m4' -=========================== - -This version of `m4' contains a few facilities that do not exist in -System V `m4'. These extra facilities are all suppressed by using the -`-G' command line option (*note Invoking m4: Limits control.), unless -overridden by other command line options. - - * In the `$'N notation for macro arguments, N can contain several - digits, while the System V `m4' only accepts one digit. This - allows macros in GNU `m4' to take any number of arguments, and not - only nine (*note Arguments::). - - This means that `define(`foo', `$11')' is ambiguous between - implementations. To portably choose between grabbing the first - parameter and appending 1 to the expansion, or grabbing the - eleventh parameter, you can do the following: - - define(`a1', `A1') - => - dnl First argument, concatenated with 1 - define(`_1', `$1')define(`first1', `_1($@)1') - => - dnl Eleventh argument, portable - define(`_9', `$9')define(`eleventh', `_9(shift(shift($@)))') - => - dnl Eleventh argument, GNU style - define(`Eleventh', `$11') - => - first1(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') - =>A1 - eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') - =>k - Eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') - =>k - - * The `divert' (*note Divert::) macro can manage more than 9 - diversions. GNU `m4' treats all positive numbers as valid - diversions, rather than discarding diversions greater than 9. - - * Files included with `include' and `sinclude' are sought in a user - specified search path, if they are not found in the working - directory. The search path is specified by the `-I' option and the - `M4PATH' environment variable (*note Search Path::). - - * Arguments to `undivert' can be non-numeric, in which case the named - file will be included uninterpreted in the output (*note - Undivert::). - - * Formatted output is supported through the `format' builtin, which - is modeled after the C library function `printf' (*note Format::). - - * Searches and text substitution through regular expressions are - supported by the `regexp' (*note Regexp::) and `patsubst' (*note - Patsubst::) builtins. - - * The output of shell commands can be read into `m4' with `esyscmd' - (*note Esyscmd::). - - * There is indirect access to any builtin macro with `builtin' - (*note Builtin::). - - * Macros can be called indirectly through `indir' (*note Indir::). - - * The name of the program, the current input file, and the current - input line number are accessible through the builtins - `__program__', `__file__', and `__line__' (*note Location::). - - * The format of the output from `dumpdef' and macro tracing can be - controlled with `debugmode' (*note Debug Levels::). - - * The destination of trace and debug output can be controlled with - `debugfile' (*note Debug Output::). - - * The `maketemp' (*note Mkstemp::) macro behaves like `mkstemp', - creating a new file with a unique name on every invocation, rather - than following the insecure behavior of replacing the trailing `X' - characters with the `m4' process id. - - In addition to the above extensions, GNU `m4' implements the -following command line options: `-F', `-G', `-I', `-L', `-R', `-V', -`-W', `-d', `-i', `-l', `--debugfile' and `-t'. *Note Invoking m4::, -for a description of these options. - - Also, the debugging and tracing facilities in GNU `m4' are much more -extensive than in most other versions of `m4'. - - -File: m4.info, Node: Incompatibilities, Next: Other Incompatibilities, Prev: Extensions, Up: Compatibility - -16.2 Facilities in System V `m4' not in GNU `m4' -================================================ - -The version of `m4' from System V contains a few facilities that have -not been implemented in GNU `m4' yet. Additionally, POSIX requires -some behaviors that GNU `m4' has not implemented yet. Relying on these -behaviors is non-portable, as a future release of GNU `m4' may change. - - * System V `m4' supports multiple arguments to `defn', and POSIX - requires it. This is not yet implemented in GNU `m4'. - Unfortunately, this means it is not possible to mix builtins and - other text into a single macro; a helper macro is required. - - * POSIX requires an application to exit with non-zero status if it - wrote an error message to stderr. This has not yet been - consistently implemented for the various builtins that are - required to issue an error (such as `include' (*note Include::) - when a file is unreadable, `eval' (*note Eval::) when an argument - cannot be parsed, or using `m4exit' (*note M4exit::) with a - non-numeric argument). - - * Some traditional implementations only allow reading standard input - once, but GNU `m4' correctly handles multiple instances of `-' on - the command line. - - * POSIX requires `m4wrap' (*note M4wrap::) to act in FIFO (first-in, - first-out) order, but GNU `m4' currently uses LIFO order. - Furthermore, POSIX states that only the first argument to `m4wrap' - is saved for later evaluation, bug GNU `m4' saves and processes - all arguments, with output separated by spaces. - - However, it is possible to emulate POSIX behavior by including the - file `m4-1.4.8/examples/wrapfifo.m4' from the distribution: - - undivert(`wrapfifo.m4')dnl - =>dnl Redefine m4wrap to have FIFO semantics. - =>define(`_m4wrap_level', `0')dnl - =>define(`m4wrap', - =>`ifdef(`m4wrap'_m4wrap_level, - => `define(`m4wrap'_m4wrap_level, - => defn(`m4wrap'_m4wrap_level)`$1')', - => `builtin(`m4wrap', `define(`_m4wrap_level', - => incr(_m4wrap_level))dnl - =>m4wrap'_m4wrap_level)dnl - =>define(`m4wrap'_m4wrap_level, `$1')')')dnl - include(`wrapfifo.m4') - => - m4wrap(`a`'m4wrap(`c - ', `d')')m4wrap(`b') - => - ^D - =>abc - - * POSIX requires that all builtins that require arguments, but are - called without arguments, behave as though empty strings had been - passed. For example, `a`'define`'b' would expand to `ab'. But - GNU `m4' ignores certain builtins if they have missing arguments, - giving `adefineb' for the above example. - - * Traditional implementations handle `define(`f',`1')' (*note - Define::) by undefining the entire stack of previous definitions, - and if doing `undefine(`f')' first. GNU `m4' replaces just the top - definition on the stack, as if doing `popdef(`f')' followed by - `pushdef(`f',`1')'. - - * POSIX requires `syscmd' (*note Syscmd::) to evaluate command - output for macro expansion, but this appears to be a mistake in - POSIX since traditional implementations did not do this. GNU `m4' - follows traditional behavior in `syscmd', and provides the - extension `esyscmd' that provides the POSIX semantics. - - * At one point, POSIX required `changequote(ARG)' (*note - Changequote::) to use newline as the close quote, but this was a - bug, and the next version of POSIX is anticipated to state that - using empty strings or just one argument is unspecified. - Meanwhile, the GNU `m4' behavior of treating an empty end-quote - delimiter as `'' is not portable, as Solaris treats it as - repeating the start-quote delimiter, and BSD treats it as leaving - the previous end-quote delimiter unchanged. For predictable - results, never call changequote with just one argument, or with - empty strings for arguments. - - * At one point, POSIX required `changecom(ARG,)' (*note Changecom::) - to make it impossible to end a comment, but this is a bug, and the - next version of POSIX is anticipated to state that using empty - strings is unspecified. Meanwhile, the GNU `m4' behavior of - treating an empty end-comment delimiter as newline is not - portable, as BSD treats it as leaving the previous end-comment - delimiter unchanged. It is also impossible in BSD implementations - to disable comments, even though that is required by POSIX. For - predictable results, never call changecom with empty strings for - arguments. - - * Most implementations of `m4' give macros a higher precedence than - comments when parsing, meaning that if the start delimiter given to - `changecom' (*note Changecom::) starts with a macro name, comments - are effectively disabled. POSIX does not specify what the - precedence is, so the GNU `m4' parser recognizes comments, then - macros, then quoted strings. - - * Traditional implementations allow argument collection, but not - string and comment processing, to span file boundaries. Thus, if - `a.m4' contains `len(', and `b.m4' contains `abc)', `m4 a.m4 b.m4' - outputs `3' with traditional `m4', but gives an error message that - the end of file was encountered inside a macro with GNU `m4'. On - the other hand, traditional implementations do end of file - processing for files included with `include' or `sinclude' (*note - Include::), while GNU `m4' seamlessly integrates the content of - those files. Thus `include(`a.m4')include(`b.m4')' will output - `3' instead of giving an error. - - * Traditional `m4' treats `traceon' (*note Trace::) without - arguments as a global variable, independent of named macro tracing. - Also, once a macro is undefined, named tracing of that macro is - lost. On the other hand, when GNU `m4' encounters `traceon' - without arguments, it turns tracing on for all existing - definitions at the time, but does not trace future definitions; - `traceoff' without arguments turns tracing off for all definitions - regardless of whether they were also traced by name; and tracing - by name, such as with `-tfoo' at the command line or - `traceon(`foo')' in the input, is an attribute that is preserved - even if the macro is currently undefined. - - * POSIX requires `eval' (*note Eval::) to treat all operators with - the same precedence as C. However, GNU `m4' currently follows the - traditional precedence of other `m4' implementations, where - bitwise and logical negation (`~' and `!') have lower precedence - than equality operators, rather than equal precedence with other - unary operators. Use explicit parentheses to ensure proper - precedence. As extensions to POSIX, GNU `m4' treats the shift - operators `<<' and `>>' as well-defined on signed integers (even - though they are not in C), and adds the exponentiation operator - `**'. - - * POSIX requires `translit' (*note Translit::) to treat each - character of the second and third arguments literally, but GNU - `m4' treats `-' as a range operator. - - * POSIX requires `m4' to honor the locale environment variables of - `LANG', `LC_ALL', `LC_CTYPE', `LC_MESSAGES', and `NLSPATH', but - this has not yet been implemented in GNU `m4'. - - * POSIX states that only unquoted leading newlines and blanks (that - is, space and tab) are ignored when collecting macro arguments. - However, this appears to be a bug in POSIX, since most traditional - implementations also ignore all whitespace (formfeed, carriage - return, and vertical tab). GNU `m4' follows tradition and ignores - all leading unquoted whitespace. - - -File: m4.info, Node: Other Incompatibilities, Prev: Incompatibilities, Up: Compatibility - -16.3 Other incompatibilities -============================ - -There are a few other incompatibilities between this implementation of -`m4', and the System V version. - - * GNU `m4' implements sync lines differently from System V `m4', - when text is being diverted. GNU `m4' outputs the sync lines when - the text is being diverted, and System V `m4' when the diverted - text is being brought back. - - The problem is which lines and file names should be attached to - text that is being, or has been, diverted. System V `m4' regards - all the diverted text as being generated by the source line - containing the `undivert' call, whereas GNU `m4' regards the - diverted text as being generated at the time it is diverted. - - The sync line option is used mostly when using `m4' as a front end - to a compiler. If a diverted line causes a compiler error, the - error messages should most probably refer to the place where the - diversion were made, and not where it was inserted again. - - * GNU `m4' makes no attempt at prohibiting self-referential - definitions like: - - define(`x', `x') - => - define(`x', `x ') - => - - There is nothing inherently wrong with defining `x' to return `x'. - The wrong thing is to expand `x' unquoted. In `m4', one might - use macros to hold strings, as we do for variables in other - programming languages, further checking them with: - - ifelse(defn(`HOLDER'), `VALUE', ...) - - In cases like this one, an interdiction for a macro to hold its own - name would be a useless limitation. Of course, this leaves more - rope for the GNU `m4' user to hang himself! Rescanning hangs may - be avoided through careful programming, a little like for endless - loops in traditional programming languages. - - -File: m4.info, Node: Answers, Next: Copying This Manual, Prev: Compatibility, Up: Top - -17 Correct version of some examples -*********************************** - -Some of the examples in this manuals are buggy or not very robust, for -demonstration purposes. Improved versions of these composite macros are -presented here. - -* Menu: - -* Improved exch:: Solution for `exch' -* Improved forloop:: Solution for `forloop' -* Improved foreach:: Solution for `foreach' -* Improved cleardivert:: Solution for `cleardivert' -* Improved fatal_error:: Solution for `fatal_error' - - -File: m4.info, Node: Improved exch, Next: Improved forloop, Up: Answers - -17.1 Solution for `exch' -======================== - -The `exch' macro (*note Arguments::) as presented requires clients to -double quote their arguments. A nicer definition, which lets clients -follow the rule of thumb of one level of quoting per level of -parentheses, involves adding quotes in the definition of `exch', as -follows: - - define(`exch', ``$2', `$1'') - => - define(exch(`expansion text', `macro')) - => - macro - =>expansion text - - -File: m4.info, Node: Improved forloop, Next: Improved foreach, Prev: Improved exch, Up: Answers - -17.2 Solution for `forloop' -=========================== - -The `forloop' macro (*note Forloop::) as presented earlier can go into -an infinite loop if given an iterator that is not parsed as a macro -name. It does not do any sanity checking on its numeric bounds, and -only permits decimal numbers for bounds. Here is an improved version, -shipped as `m4-1.4.8/examples/forloop2.m4'; this version also optimizes -based on the fact that the starting bound does not need to be passed to -the helper `_forloop'. - - undivert(`forloop2.m4')dnl - =>divert(`-1') - =># forloop(var, from, to, stmt) - improved version: - =># works even if VAR is not a strict macro name - =># performs sanity check that FROM is larger than TO - =># allows complex numerical expressions in TO and FROM - =>define(`forloop', `ifelse(eval(`($3) >= ($2)'), `1', - => `pushdef(`$1', eval(`$2'))_forloop(`$1', - => eval(`$3'), `$4')popdef(`$1')')') - =>define(`_forloop', - => `$3`'ifelse(indir(`$1'), `$2', `', - => `define(`$1', incr(indir(`$1')))$0($@)')') - =>divert`'dnl - include(`forloop2.m4') - => - forloop(`i', `2', `1', `no iteration occurs') - => - forloop(`', `1', `2', ` odd iterator name') - => odd iterator name odd iterator name - forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')') - => 0xa 0xb 0xc - forloop(`i', `a', `b', `non-numeric bounds') - error-->m4:stdin:6: bad expression in eval (bad input): (b) >= (a) - => - - Of course, it is possible to make even more improvements, such as -adding an optional step argument, or allowing iteration through -descending sequences. GNU Autoconf provides some of these additional -bells and whistles in its `m4_for' macro. - - -File: m4.info, Node: Improved foreach, Next: Improved cleardivert, Prev: Improved forloop, Up: Answers - -17.3 Solution for `foreach' -=========================== - -The `foreach' and `foreachq' macros (*note Foreach::) as presented -earlier each have flaws. First, we will examine and fix the quadratic -behavior of `foreachq': - - include(`foreachq.m4') - => - traceon(`shift')debugmode(`aq') - => - foreachq(`x', ``1', `2', `3', `4'', `x - ')dnl - =>1 - error-->m4trace: -3- shift(`1', `2', `3', `4') - error-->m4trace: -2- shift(`1', `2', `3', `4') - =>2 - error-->m4trace: -4- shift(`1', `2', `3', `4') - error-->m4trace: -3- shift(`2', `3', `4') - error-->m4trace: -3- shift(`1', `2', `3', `4') - error-->m4trace: -2- shift(`2', `3', `4') - =>3 - error-->m4trace: -5- shift(`1', `2', `3', `4') - error-->m4trace: -4- shift(`2', `3', `4') - error-->m4trace: -3- shift(`3', `4') - error-->m4trace: -4- shift(`1', `2', `3', `4') - error-->m4trace: -3- shift(`2', `3', `4') - error-->m4trace: -2- shift(`3', `4') - =>4 - error-->m4trace: -6- shift(`1', `2', `3', `4') - error-->m4trace: -5- shift(`2', `3', `4') - error-->m4trace: -4- shift(`3', `4') - error-->m4trace: -3- shift(`4') - - Each successive iteration was adding more quoted `shift' -invocations, and the entire list contents were passing through every -iteration. In general, when recursing, it is a good idea to make the -recursion use fewer arguments, rather than adding additional quoted -uses of `shift'. By doing so, `m4' uses less memory, invokes fewer -macros, is less likely to run into machine limits, and most -importantly, performs faster. The fixed version of `foreachq' can be -found in `m4-1.4.8/examples/foreachq2.m4': - - include(`foreachq2.m4') - => - undivert(`foreachq2.m4')dnl - =>include(`quote.m4')dnl - =>divert(`-1') - =># foreachq(x, `item_1, item_2, ..., item_n', stmt) - =># quoted list, improved version - =>define(`foreachq', `pushdef(`$1')_foreachq($@)popdef(`$1')') - =>define(`_arg1q', ``$1'') - =>define(`_rest', `ifelse(`$#', `1', `', `dquote(shift($@))')') - =>define(`_foreachq', `ifelse(`$2', `', `', - => `define(`$1', _arg1q($2))$3`'$0(`$1', _rest($2), `$3')')') - =>divert`'dnl - traceon(`shift')debugmode(`aq') - => - foreachq(`x', ``1', `2', `3', `4'', `x - ')dnl - =>1 - error-->m4trace: -3- shift(`1', `2', `3', `4') - =>2 - error-->m4trace: -3- shift(`2', `3', `4') - =>3 - error-->m4trace: -3- shift(`3', `4') - =>4 - - Note that the fixed version calls unquoted helper macros in -`_foreachq' to trim elements immediately; those helper macros in turn -must re-supply the layer of quotes lost in the macro invocation. -Contrast the use of `_arg1q', which quotes the first list element, with -`_arg1' of the earlier implementation that returned the first list -element directly. - - For a different approach, the improved version of `foreach', -available in `m4-1.4.8/examples/foreach2.m4', simply overquotes the -arguments to `_foreach' to begin with, using `dquote_elt'. Then -`_foreach' can just use `_arg1' to remove the extra layer of quoting -that was added up front: - - include(`foreach2.m4') - => - undivert(`foreach2.m4')dnl - =>include(`quote.m4')dnl - =>divert(`-1') - =># foreach(x, (item_1, item_2, ..., item_n), stmt) - =># parenthesized list, improved version - =>define(`foreach', `pushdef(`$1')_foreach(`$1', - => (dquote(dquote_elt$2)), `$3')popdef(`$1')') - =>define(`_arg1', `$1') - =>define(`_foreach', `ifelse(`$2', `(`')', `', - => `define(`$1', _arg1$2)$3`'$0(`$1', (dquote(shift$2)), `$3')')') - =>divert`'dnl - traceon(`shift')debugmode(`aq') - => - foreach(`x', `(`1', `2', `3', `4')', `x - ')dnl - error-->m4trace: -4- shift(`1', `2', `3', `4') - error-->m4trace: -4- shift(`2', `3', `4') - error-->m4trace: -4- shift(`3', `4') - =>1 - error-->m4trace: -3- shift(``1'', ``2'', ``3'', ``4'') - =>2 - error-->m4trace: -3- shift(``2'', ``3'', ``4'') - =>3 - error-->m4trace: -3- shift(``3'', ``4'') - =>4 - error-->m4trace: -3- shift(``4'') - - In summary, recursion over list elements is trickier than it -appeared at first glance, but provides a powerful idiom within `m4' -processing. As a final demonstration, both list styles are now able to -handle several scenarios that would wreak havoc on the original -implementations. This points out one other difference between the two -list styles. `foreach' evaluates unquoted list elements only once, in -preparation for calling `_foreach'. But `foreachq' evaluates unquoted -list elements twice while visiting the first list element, once in -`_arg1q' and once in `_rest'. When deciding which list style to use, -one must take into account whether repeating the side effects of -unquoted list elements will have any detrimental effects. - - include(`foreach2.m4') - => - include(`foreachq2.m4') - => - dnl 0-element list: - foreach(`x', `', `') / foreachq(`x', `', `') - => / - dnl 1-element list of empty element - foreach(`x', `()', `') / foreachq(`x', ``'', `') - =><> / <> - dnl 2-element list of empty elements - foreach(`x', `(`',`')', `') / foreachq(`x', ``',`'', `') - =><><> / <><> - dnl 1-element list of a comma - foreach(`x', `(`,')', `') / foreachq(`x', ``,'', `') - =><,> / <,> - dnl 2-element list of unbalanced parentheses - foreach(`x', `(`(', `)')', `') / foreachq(`x', ``(', `)'', `') - =><(><)> / <(><)> - define(`active', `ACT, IVE') - => - traceon(`active') - => - 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' - => - => - => - => - foreachq(`x', `active, active', ` - ')dnl - error-->m4trace: -3- active -> `ACT, IVE' - error-->m4trace: -3- active -> `ACT, IVE' - => - error-->m4trace: -3- active -> `ACT, IVE' - error-->m4trace: -3- active -> `ACT, IVE' - => - => - => - dnl list of quoted macros; expansion occurs during recursion - foreach(`x', `(`active', `active')', ` - ')dnl - error-->m4trace: -1- active -> `ACT, IVE' - => - error-->m4trace: -1- active -> `ACT, IVE' - => - foreachq(`x', ``active', `active'', ` - ')dnl - error-->m4trace: -1- active -> `ACT, IVE' - => - error-->m4trace: -1- active -> `ACT, IVE' - => - dnl list of double-quoted macro names; no expansion - foreach(`x', `(``active'', ``active'')', ` - ')dnl - => - => - foreachq(`x', ```active'', ``active''', ` - ')dnl - => - => - - -File: m4.info, Node: Improved cleardivert, Next: Improved fatal_error, Prev: Improved foreach, Up: Answers - -17.4 Solution for `cleardivert' -=============================== - -The `cleardivert' macro (*note Cleardivert::) cannot, as it stands, be -called without arguments to clear all pending diversions. That is -because using undivert with an empty string for an argument is different -than using it with no arguments at all. Compare the earlier definition -with one that takes the number of arguments into account: - - define(`cleardivert', - `pushdef(`_n', divnum)divert(`-1')undivert($@)divert(_n)popdef(`_n')') - => - divert(`1')one - divert - => - cleardivert - => - undivert - =>one - => - define(`cleardivert', - `pushdef(`_num', divnum)divert(`-1')ifelse(`$#', `0', - `undivert`'', `undivert($@)')divert(_num)popdef(`_num')') - => - divert(`2')two - divert - => - cleardivert - => - undivert - => - - -File: m4.info, Node: Improved fatal_error, Prev: Improved cleardivert, Up: Answers - -17.5 Solution for `fatal_error' -=============================== - -The `fatal_error' macro (*note M4exit::) is not robust to versions of -GNU M4 earlier than 1.4.8, where invoking `__file__' (*note Location::) -inside `m4wrap' would result in an empty string, and `__line__' -resulted in `0' even though all files start at line 1. Furthermore, -versions earlier than 1.4.6 did not support the `__program__' macro. -If you want `fatal_error' to work across the entire 1.4.x release -series, a better implementation would be: - - define(`fatal_error', - `errprint(ifdef(`__program__', `__program__', ``m4'')'dnl - `:ifelse(__line__, `0', `', - `__file__:__line__:')` fatal error: $* - ')m4exit(`1')') - => - m4wrap(`divnum(`demo of internal message') - fatal_error(`inside wrapped text')') - => - ^D - error-->m4:stdin:6: Warning: excess arguments to builtin `divnum' ignored - =>0 - error-->m4:stdin:6: fatal error: inside wrapped text - - -File: m4.info, Node: Copying This Manual, Next: Indices, Prev: Answers, Up: Top - -Appendix A How to make copies of this manual -******************************************** - -* Menu: - -* GNU Free Documentation License:: License for copying this manual - - -File: m4.info, Node: GNU Free Documentation License, Up: Copying This Manual - -A.1 GNU Free Documentation License -================================== - - Version 1.2, November 2002 - - Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - 0. PREAMBLE - - The purpose of this License is to make a manual, textbook, or other - functional and useful document "free" in the sense of freedom: to - assure everyone the effective freedom to copy and redistribute it, - with or without modifying it, either commercially or - noncommercially. Secondarily, this License preserves for the - author and publisher a way to get credit for their work, while not - being considered responsible for modifications made by others. - - This License is a kind of "copyleft", which means that derivative - works of the document must themselves be free in the same sense. - It complements the GNU General Public License, which is a copyleft - license designed for free software. - - We have designed this License in order to use it for manuals for - free software, because free software needs free documentation: a - free program should come with manuals providing the same freedoms - that the software does. But this License is not limited to - software manuals; it can be used for any textual work, regardless - of subject matter or whether it is published as a printed book. - We recommend this License principally for works whose purpose is - instruction or reference. - - 1. APPLICABILITY AND DEFINITIONS - - This License applies to any manual or other work, in any medium, - that contains a notice placed by the copyright holder saying it - can be distributed under the terms of this License. Such a notice - grants a world-wide, royalty-free license, unlimited in duration, - to use that work under the conditions stated herein. The - "Document", below, refers to any such manual or work. Any member - of the public is a licensee, and is addressed as "you". You - accept the license if you copy, modify or distribute the work in a - way requiring permission under copyright law. - - A "Modified Version" of the Document means any work containing the - Document or a portion of it, either copied verbatim, or with - modifications and/or translated into another language. - - A "Secondary Section" is a named appendix or a front-matter section - of the Document that deals exclusively with the relationship of the - publishers or authors of the Document to the Document's overall - subject (or to related matters) and contains nothing that could - fall directly within that overall subject. (Thus, if the Document - is in part a textbook of mathematics, a Secondary Section may not - explain any mathematics.) The relationship could be a matter of - historical connection with the subject or with related matters, or - of legal, commercial, philosophical, ethical or political position - regarding them. - - The "Invariant Sections" are certain Secondary Sections whose - titles are designated, as being those of Invariant Sections, in - the notice that says that the Document is released under this - License. If a section does not fit the above definition of - Secondary then it is not allowed to be designated as Invariant. - The Document may contain zero Invariant Sections. If the Document - does not identify any Invariant Sections then there are none. - - The "Cover Texts" are certain short passages of text that are - listed, as Front-Cover Texts or Back-Cover Texts, in the notice - that says that the Document is released under this License. A - Front-Cover Text may be at most 5 words, and a Back-Cover Text may - be at most 25 words. - - A "Transparent" copy of the Document means a machine-readable copy, - represented in a format whose specification is available to the - general public, that is suitable for revising the document - straightforwardly with generic text editors or (for images - composed of pixels) generic paint programs or (for drawings) some - widely available drawing editor, and that is suitable for input to - text formatters or for automatic translation to a variety of - formats suitable for input to text formatters. A copy made in an - otherwise Transparent file format whose markup, or absence of - markup, has been arranged to thwart or discourage subsequent - modification by readers is not Transparent. An image format is - not Transparent if used for any substantial amount of text. A - copy that is not "Transparent" is called "Opaque". - - Examples of suitable formats for Transparent copies include plain - ASCII without markup, Texinfo input format, LaTeX input format, - SGML or XML using a publicly available DTD, and - standard-conforming simple HTML, PostScript or PDF designed for - human modification. Examples of transparent image formats include - PNG, XCF and JPG. Opaque formats include proprietary formats that - can be read and edited only by proprietary word processors, SGML or - XML for which the DTD and/or processing tools are not generally - available, and the machine-generated HTML, PostScript or PDF - produced by some word processors for output purposes only. - - The "Title Page" means, for a printed book, the title page itself, - plus such following pages as are needed to hold, legibly, the - material this License requires to appear in the title page. For - works in formats which do not have any title page as such, "Title - Page" means the text near the most prominent appearance of the - work's title, preceding the beginning of the body of the text. - - A section "Entitled XYZ" means a named subunit of the Document - whose title either is precisely XYZ or contains XYZ in parentheses - following text that translates XYZ in another language. (Here XYZ - stands for a specific section name mentioned below, such as - "Acknowledgements", "Dedications", "Endorsements", or "History".) - To "Preserve the Title" of such a section when you modify the - Document means that it remains a section "Entitled XYZ" according - to this definition. - - The Document may include Warranty Disclaimers next to the notice - which states that this License applies to the Document. These - Warranty Disclaimers are considered to be included by reference in - this License, but only as regards disclaiming warranties: any other - implication that these Warranty Disclaimers may have is void and - has no effect on the meaning of this License. - - 2. VERBATIM COPYING - - You may copy and distribute the Document in any medium, either - commercially or noncommercially, provided that this License, the - copyright notices, and the license notice saying this License - applies to the Document are reproduced in all copies, and that you - add no other conditions whatsoever to those of this License. You - may not use technical measures to obstruct or control the reading - or further copying of the copies you make or distribute. However, - you may accept compensation in exchange for copies. If you - distribute a large enough number of copies you must also follow - the conditions in section 3. - - You may also lend copies, under the same conditions stated above, - and you may publicly display copies. - - 3. COPYING IN QUANTITY - - If you publish printed copies (or copies in media that commonly - have printed covers) of the Document, numbering more than 100, and - the Document's license notice requires Cover Texts, you must - enclose the copies in covers that carry, clearly and legibly, all - these Cover Texts: Front-Cover Texts on the front cover, and - Back-Cover Texts on the back cover. Both covers must also clearly - and legibly identify you as the publisher of these copies. The - front cover must present the full title with all words of the - title equally prominent and visible. You may add other material - on the covers in addition. Copying with changes limited to the - covers, as long as they preserve the title of the Document and - satisfy these conditions, can be treated as verbatim copying in - other respects. - - If the required texts for either cover are too voluminous to fit - legibly, you should put the first ones listed (as many as fit - reasonably) on the actual cover, and continue the rest onto - adjacent pages. - - If you publish or distribute Opaque copies of the Document - numbering more than 100, you must either include a - machine-readable Transparent copy along with each Opaque copy, or - state in or with each Opaque copy a computer-network location from - which the general network-using public has access to download - using public-standard network protocols a complete Transparent - copy of the Document, free of added material. If you use the - latter option, you must take reasonably prudent steps, when you - begin distribution of Opaque copies in quantity, to ensure that - this Transparent copy will remain thus accessible at the stated - location until at least one year after the last time you - distribute an Opaque copy (directly or through your agents or - retailers) of that edition to the public. - - It is requested, but not required, that you contact the authors of - the Document well before redistributing any large number of - copies, to give them a chance to provide you with an updated - version of the Document. - - 4. MODIFICATIONS - - You may copy and distribute a Modified Version of the Document - under the conditions of sections 2 and 3 above, provided that you - release the Modified Version under precisely this License, with - the Modified Version filling the role of the Document, thus - licensing distribution and modification of the Modified Version to - whoever possesses a copy of it. In addition, you must do these - things in the Modified Version: - - A. Use in the Title Page (and on the covers, if any) a title - distinct from that of the Document, and from those of - previous versions (which should, if there were any, be listed - in the History section of the Document). You may use the - same title as a previous version if the original publisher of - that version gives permission. - - B. List on the Title Page, as authors, one or more persons or - entities responsible for authorship of the modifications in - the Modified Version, together with at least five of the - principal authors of the Document (all of its principal - authors, if it has fewer than five), unless they release you - from this requirement. - - C. State on the Title page the name of the publisher of the - Modified Version, as the publisher. - - D. Preserve all the copyright notices of the Document. - - E. Add an appropriate copyright notice for your modifications - adjacent to the other copyright notices. - - F. Include, immediately after the copyright notices, a license - notice giving the public permission to use the Modified - Version under the terms of this License, in the form shown in - the Addendum below. - - G. Preserve in that license notice the full lists of Invariant - Sections and required Cover Texts given in the Document's - license notice. - - H. Include an unaltered copy of this License. - - I. Preserve the section Entitled "History", Preserve its Title, - and add to it an item stating at least the title, year, new - authors, and publisher of the Modified Version as given on - the Title Page. If there is no section Entitled "History" in - the Document, create one stating the title, year, authors, - and publisher of the Document as given on its Title Page, - then add an item describing the Modified Version as stated in - the previous sentence. - - J. Preserve the network location, if any, given in the Document - for public access to a Transparent copy of the Document, and - likewise the network locations given in the Document for - previous versions it was based on. These may be placed in - the "History" section. You may omit a network location for a - work that was published at least four years before the - Document itself, or if the original publisher of the version - it refers to gives permission. - - K. For any section Entitled "Acknowledgements" or "Dedications", - Preserve the Title of the section, and preserve in the - section all the substance and tone of each of the contributor - acknowledgements and/or dedications given therein. - - L. Preserve all the Invariant Sections of the Document, - unaltered in their text and in their titles. Section numbers - or the equivalent are not considered part of the section - titles. - - M. Delete any section Entitled "Endorsements". Such a section - may not be included in the Modified Version. - - N. Do not retitle any existing section to be Entitled - "Endorsements" or to conflict in title with any Invariant - Section. - - O. Preserve any Warranty Disclaimers. - - If the Modified Version includes new front-matter sections or - appendices that qualify as Secondary Sections and contain no - material copied from the Document, you may at your option - designate some or all of these sections as invariant. To do this, - add their titles to the list of Invariant Sections in the Modified - Version's license notice. These titles must be distinct from any - other section titles. - - You may add a section Entitled "Endorsements", provided it contains - nothing but endorsements of your Modified Version by various - parties--for example, statements of peer review or that the text - has been approved by an organization as the authoritative - definition of a standard. - - You may add a passage of up to five words as a Front-Cover Text, - and a passage of up to 25 words as a Back-Cover Text, to the end - of the list of Cover Texts in the Modified Version. Only one - passage of Front-Cover Text and one of Back-Cover Text may be - added by (or through arrangements made by) any one entity. If the - Document already includes a cover text for the same cover, - previously added by you or by arrangement made by the same entity - you are acting on behalf of, you may not add another; but you may - replace the old one, on explicit permission from the previous - publisher that added the old one. - - The author(s) and publisher(s) of the Document do not by this - License give permission to use their names for publicity for or to - assert or imply endorsement of any Modified Version. - - 5. COMBINING DOCUMENTS - - You may combine the Document with other documents released under - this License, under the terms defined in section 4 above for - modified versions, provided that you include in the combination - all of the Invariant Sections of all of the original documents, - unmodified, and list them all as Invariant Sections of your - combined work in its license notice, and that you preserve all - their Warranty Disclaimers. - - The combined work need only contain one copy of this License, and - multiple identical Invariant Sections may be replaced with a single - copy. If there are multiple Invariant Sections with the same name - but different contents, make the title of each such section unique - by adding at the end of it, in parentheses, the name of the - original author or publisher of that section if known, or else a - unique number. Make the same adjustment to the section titles in - the list of Invariant Sections in the license notice of the - combined work. - - In the combination, you must combine any sections Entitled - "History" in the various original documents, forming one section - Entitled "History"; likewise combine any sections Entitled - "Acknowledgements", and any sections Entitled "Dedications". You - must delete all sections Entitled "Endorsements." - - 6. COLLECTIONS OF DOCUMENTS - - You may make a collection consisting of the Document and other - documents released under this License, and replace the individual - copies of this License in the various documents with a single copy - that is included in the collection, provided that you follow the - rules of this License for verbatim copying of each of the - documents in all other respects. - - You may extract a single document from such a collection, and - distribute it individually under this License, provided you insert - a copy of this License into the extracted document, and follow - this License in all other respects regarding verbatim copying of - that document. - - 7. AGGREGATION WITH INDEPENDENT WORKS - - A compilation of the Document or its derivatives with other - separate and independent documents or works, in or on a volume of - a storage or distribution medium, is called an "aggregate" if the - copyright resulting from the compilation is not used to limit the - legal rights of the compilation's users beyond what the individual - works permit. When the Document is included in an aggregate, this - License does not apply to the other works in the aggregate which - are not themselves derivative works of the Document. - - If the Cover Text requirement of section 3 is applicable to these - copies of the Document, then if the Document is less than one half - of the entire aggregate, the Document's Cover Texts may be placed - on covers that bracket the Document within the aggregate, or the - electronic equivalent of covers if the Document is in electronic - form. Otherwise they must appear on printed covers that bracket - the whole aggregate. - - 8. TRANSLATION - - Translation is considered a kind of modification, so you may - distribute translations of the Document under the terms of section - 4. Replacing Invariant Sections with translations requires special - permission from their copyright holders, but you may include - translations of some or all Invariant Sections in addition to the - original versions of these Invariant Sections. You may include a - translation of this License, and all the license notices in the - Document, and any Warranty Disclaimers, provided that you also - include the original English version of this License and the - original versions of those notices and disclaimers. In case of a - disagreement between the translation and the original version of - this License or a notice or disclaimer, the original version will - prevail. - - If a section in the Document is Entitled "Acknowledgements", - "Dedications", or "History", the requirement (section 4) to - Preserve its Title (section 1) will typically require changing the - actual title. - - 9. TERMINATION - - You may not copy, modify, sublicense, or distribute the Document - except as expressly provided for under this License. Any other - attempt to copy, modify, sublicense or distribute the Document is - void, and will automatically terminate your rights under this - License. However, parties who have received copies, or rights, - from you under this License will not have their licenses - terminated so long as such parties remain in full compliance. - - 10. FUTURE REVISIONS OF THIS LICENSE - - The Free Software Foundation may publish new, revised versions of - the GNU Free Documentation 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. See - `http://www.gnu.org/copyleft/'. - - Each version of the License is given a distinguishing version - number. If the Document specifies that a particular numbered - version of this License "or any later version" applies to it, you - have the option of following the terms and conditions either of - that specified version or of any later version that has been - published (not as a draft) by the Free Software Foundation. If - the Document does not specify a version number of this License, - you may choose any version ever published (not as a draft) by the - Free Software Foundation. - -ADDENDUM: How to use this License for your documents -==================================================== - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and license -notices just after the title page: - - Copyright (C) YEAR YOUR NAME. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.2 - 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''. - - If you have Invariant Sections, Front-Cover Texts and Back-Cover -Texts, replace the "with...Texts." line with this: - - with the Invariant Sections being LIST THEIR TITLES, with - the Front-Cover Texts being LIST, and with the Back-Cover Texts - being LIST. - - If you have Invariant Sections without Cover Texts, or some other -combination of the three, merge those two alternatives to suit the -situation. - - If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of -free software license, such as the GNU General Public License, to -permit their use in free software. - - -File: m4.info, Node: Indices, Prev: Copying This Manual, Up: Top - -Appendix B Indices of concepts and macros -***************************************** - -* Menu: - -* Concept index:: Index for many concepts -* Macro index:: Index for all `m4' macros - - -File: m4.info, Node: Concept index, Next: Macro index, Up: Indices - -B.1 Index for many concepts -=========================== - -[index] -* Menu: - -* arguments to macros: Macro Arguments. (line 6) -* Arguments to macros: Arguments. (line 6) -* arguments to macros, special: Pseudo Arguments. (line 6) -* arguments, quoted macro: Quoting Arguments. (line 6) -* arithmetic: Arithmetic. (line 6) -* arrays: Define. (line 52) -* builtins, indirect call of: Builtin. (line 6) -* call of builtins, indirect: Builtin. (line 6) -* call of macros, indirect: Indir. (line 6) -* changing comment delimiters: Changecom. (line 6) -* changing the quote delimiters: Changequote. (line 6) -* characters, translating: Translit. (line 6) -* command line, file names on the: Command line files. (line 6) -* command line, macro definitions on the: Preprocessor features. - (line 6) -* command line, options: Invoking m4. (line 10) -* commands, exit status from shell: Sysval. (line 6) -* commands, running shell: Shell commands. (line 6) -* commands, running UNIX: Shell commands. (line 6) -* comment delimiters, changing: Changecom. (line 6) -* comments: Comments. (line 6) -* comments, copied to output: Changecom. (line 29) -* comparing strings: Ifelse. (line 6) -* compatibility: Compatibility. (line 6) -* conditionals: Ifdef. (line 6) -* controlling debugging output: Debug Levels. (line 6) -* counting loops: Forloop. (line 6) -* debugging output, controlling: Debug Levels. (line 6) -* debugging output, saving: Debug Output. (line 6) -* decrement operator: Incr. (line 6) -* defining new macros: Definitions. (line 6) -* definitions, displaying macro: Dumpdef. (line 6) -* deleting macros: Undefine. (line 6) -* deleting whitespace in input: Dnl. (line 6) -* discarding diverted text: Cleardivert. (line 6) -* displaying macro definitions: Dumpdef. (line 6) -* diversion numbers: Divnum. (line 6) -* diverted text, discarding: Cleardivert. (line 6) -* diverting output to files: Divert. (line 6) -* dumping into frozen file: Using frozen files. (line 6) -* error messages, printing: Errprint. (line 6) -* evaluation, of integer expressions: Eval. (line 6) -* executing shell commands: Shell commands. (line 6) -* executing UNIX commands: Shell commands. (line 6) -* exit status from shell commands: Sysval. (line 6) -* exiting from m4: M4exit. (line 6) -* expansion of macros: Macro expansion. (line 6) -* expansion, tracing macro: Trace. (line 6) -* expressions, evaluation of integer: Eval. (line 6) -* extracting substrings: Substr. (line 6) -* fast loading of frozen files: Using frozen files. (line 6) -* FDL, GNU Free Documentation License: GNU Free Documentation License. - (line 6) -* file format, frozen file: Frozen file format. (line 6) -* file inclusion <1>: Undivert. (line 81) -* file inclusion: File Inclusion. (line 6) -* file names, on the command line: Command line files. (line 6) -* files, diverting output to: Divert. (line 6) -* files, names of temporary: Mkstemp. (line 6) -* for each loops: Foreach. (line 6) -* for loops: Forloop. (line 6) -* formatted output: Format. (line 6) -* frozen file format: Frozen file format. (line 6) -* frozen files for fast loading: Using frozen files. (line 6) -* GNU extensions <1>: Indir. (line 6) -* GNU extensions <2>: Patsubst. (line 6) -* GNU extensions <3>: Extensions. (line 6) -* GNU extensions <4>: Regexp. (line 6) -* GNU extensions <5>: Using frozen files. (line 6) -* GNU extensions <6>: Format. (line 6) -* GNU extensions <7>: Undivert. (line 81) -* GNU extensions <8>: Divert. (line 54) -* GNU extensions <9>: Search Path. (line 6) -* GNU extensions <10>: Define. (line 41) -* GNU extensions <11>: Arguments. (line 32) -* GNU extensions <12>: Esyscmd. (line 6) -* GNU extensions <13>: Debug Output. (line 6) -* GNU extensions <14>: Mkstemp. (line 52) -* GNU extensions <15>: Builtin. (line 6) -* GNU extensions: Debug Levels. (line 59) -* included files, search path for: Search Path. (line 6) -* inclusion, of files <1>: Undivert. (line 81) -* inclusion, of files: File Inclusion. (line 6) -* increment operator: Incr. (line 6) -* indirect call of builtins: Builtin. (line 6) -* indirect call of macros: Indir. (line 6) -* initialization, frozen states: Using frozen files. (line 6) -* input tokens: Syntax. (line 6) -* input, saving: M4wrap. (line 6) -* integer arithmetic: Arithmetic. (line 6) -* integer expression evaluation: Eval. (line 6) -* iterating over lists: Foreach. (line 6) -* length of strings: Len. (line 6) -* lexical structure of words: Changeword. (line 6) -* License: Copying This Manual. (line 6) -* local variables: Pushdef. (line 75) -* loops: Shift. (line 10) -* loops, counting: Forloop. (line 6) -* loops, list iteration: Foreach. (line 6) -* macro definitions, on the command line: Preprocessor features. - (line 6) -* macro expansion, tracing: Trace. (line 6) -* macro invocation: Invocation. (line 6) -* macros, arguments to <1>: Macro Arguments. (line 6) -* macros, arguments to: Arguments. (line 6) -* macros, displaying definitions: Dumpdef. (line 6) -* macros, expansion of: Macro expansion. (line 6) -* macros, how to define new: Definitions. (line 6) -* macros, how to delete: Undefine. (line 6) -* macros, how to rename: Defn. (line 6) -* macros, indirect call of: Indir. (line 6) -* macros, quoted arguments to: Quoting Arguments. (line 6) -* macros, recursive: Shift. (line 6) -* macros, special arguments to: Pseudo Arguments. (line 6) -* macros, temporary redefinition of: Pushdef. (line 6) -* messages, printing error: Errprint. (line 6) -* multibranches: Ifelse. (line 66) -* names: Names. (line 6) -* options, command line: Invoking m4. (line 10) -* output, diverting to files: Divert. (line 6) -* output, formatted: Format. (line 6) -* output, saving debugging: Debug Output. (line 6) -* pattern substitution: Patsubst. (line 6) -* platform macro: Platform macros. (line 31) -* platform macros: Platform macros. (line 6) -* POSIXLY_CORRECT: Invoking m4. (line 10) -* printing error messages: Errprint. (line 6) -* quote delimiters, changing the: Changequote. (line 6) -* quoted macro arguments: Quoting Arguments. (line 6) -* quoted string: Quoted strings. (line 6) -* recursive macros: Shift. (line 6) -* redefinition of macros, temporary: Pushdef. (line 6) -* regular expressions <1>: Patsubst. (line 6) -* regular expressions: Regexp. (line 6) -* reloading a frozen file: Using frozen files. (line 6) -* renaming macros: Defn. (line 6) -* running shell commands: Shell commands. (line 6) -* running UNIX commands: Shell commands. (line 6) -* saving debugging output: Debug Output. (line 6) -* saving input: M4wrap. (line 6) -* search path for included files: Search Path. (line 6) -* shell commands, exit status from: Sysval. (line 6) -* shell commands, running: Shell commands. (line 6) -* special arguments to macros: Pseudo Arguments. (line 6) -* status of shell commands: Sysval. (line 6) -* status, setting m4 exit: M4exit. (line 6) -* strings, length of: Len. (line 6) -* substitution by regular expression: Patsubst. (line 6) -* substrings, extracting: Substr. (line 6) -* temporary file names: Mkstemp. (line 6) -* temporary redefinition of macros: Pushdef. (line 6) -* tokens: Syntax. (line 6) -* tracing macro expansion: Trace. (line 6) -* translating characters: Translit. (line 6) -* undefining macros: Undefine. (line 6) -* UNIX commands, exit status from: Sysval. (line 6) -* UNIX commands, running: Shell commands. (line 6) -* variables, local: Pushdef. (line 75) -* words, lexical structure of: Changeword. (line 6) - - -File: m4.info, Node: Macro index, Prev: Concept index, Up: Indices - -B.2 Index for all `m4' macros -============================= - -References are exclusively to the places where a builtin is introduced -the first time. - -[index] -* Menu: - -* __file__: Location. (line 10) -* __gnu__: Platform macros. (line 12) -* __line__: Location. (line 11) -* __os2__: Platform macros. (line 13) -* __program__: Location. (line 12) -* __unix__: Platform macros. (line 15) -* __windows__: Platform macros. (line 17) -* builtin: Builtin. (line 9) -* capitalize: Patsubst. (line 55) -* changecom: Changecom. (line 10) -* changequote: Changequote. (line 10) -* changeword: Changeword. (line 23) -* cleardivert: Cleardivert. (line 26) -* debugfile: Debug Output. (line 11) -* debugmode: Debug Levels. (line 63) -* decr: Incr. (line 11) -* define: Define. (line 10) -* defn: Defn. (line 10) -* divert: Divert. (line 9) -* divnum: Divnum. (line 9) -* dnl: Dnl. (line 9) -* downcase: Patsubst. (line 54) -* dquote: Shift. (line 53) -* dquote_elt: Shift. (line 54) -* dumpdef: Dumpdef. (line 10) -* errprint: Errprint. (line 9) -* esyscmd: Esyscmd. (line 9) -* eval: Eval. (line 9) -* example: Manual. (line 32) -* fatal_error: M4exit. (line 25) -* foreach: Foreach. (line 9) -* foreachq: Foreach. (line 10) -* forloop: Forloop. (line 9) -* format: Format. (line 9) -* ifdef: Ifdef. (line 10) -* ifelse: Ifelse. (line 12) -* include: Include. (line 9) -* incr: Incr. (line 10) -* index: Index macro. (line 9) -* indir: Indir. (line 9) -* len: Len. (line 9) -* m4exit: M4exit. (line 10) -* m4wrap: M4wrap. (line 14) -* maketemp: Mkstemp. (line 12) -* mkstemp: Mkstemp. (line 11) -* os2: Platform macros. (line 14) -* patsubst: Patsubst. (line 9) -* popdef: Pushdef. (line 12) -* pushdef: Pushdef. (line 11) -* quote: Shift. (line 52) -* regexp: Regexp. (line 9) -* reverse: Shift. (line 32) -* shift: Shift. (line 17) -* sinclude: Include. (line 10) -* substr: Substr. (line 9) -* syscmd: Syscmd. (line 9) -* sysval: Sysval. (line 9) -* traceoff: Trace. (line 11) -* traceon: Trace. (line 10) -* translit: Translit. (line 9) -* undefine: Undefine. (line 9) -* undivert: Undivert. (line 9) -* unix: Platform macros. (line 16) -* upcase: Patsubst. (line 53) -* windows: Platform macros. (line 18) - - - -Tag Table: -Node: Top840 -Node: Preliminaries9196 -Node: Intro9882 -Node: History11514 -Node: Bugs14146 -Node: Manual15408 -Node: Invoking m418340 -Node: Operation modes20488 -Node: Preprocessor features22199 -Node: Limits control24701 -Node: Frozen state27637 -Node: Debugging options28436 -Node: Command line files30175 -Node: Syntax31538 -Node: Names32539 -Node: Quoted strings33001 -Node: Comments33650 -Node: Other tokens34517 -Node: Input processing35095 -Node: Macros36982 -Node: Invocation37476 -Node: Inhibiting Invocation38277 -Node: Macro Arguments41848 -Node: Quoting Arguments44539 -Node: Macro expansion45861 -Node: Definitions46529 -Node: Define47314 -Node: Arguments49520 -Node: Pseudo Arguments51268 -Node: Undefine54483 -Node: Defn55613 -Node: Pushdef58346 -Node: Indir60680 -Node: Builtin62782 -Node: Conditionals64544 -Node: Ifdef65363 -Node: Ifelse66226 -Node: Shift69445 -Node: Forloop73244 -Node: Foreach75813 -Node: Debugging80792 -Node: Dumpdef81377 -Node: Trace82761 -Node: Debug Levels85449 -Node: Debug Output88255 -Node: Input Control89526 -Node: Dnl90063 -Node: Changequote91964 -Node: Changecom96760 -Node: Changeword100276 -Node: M4wrap105717 -Node: File Inclusion107978 -Node: Include108295 -Node: Search Path110895 -Node: Diversions111812 -Node: Divert113603 -Node: Undivert116129 -Node: Divnum119011 -Node: Cleardivert119475 -Node: Text handling120680 -Node: Len121403 -Node: Index macro121788 -Node: Regexp122559 -Node: Substr124808 -Node: Translit125859 -Node: Patsubst128581 -Node: Format132121 -Node: Arithmetic134188 -Node: Incr134637 -Node: Eval135412 -Node: Shell commands139821 -Node: Platform macros140743 -Node: Syscmd142487 -Node: Esyscmd144292 -Node: Sysval145340 -Node: Mkstemp146895 -Node: Miscellaneous150197 -Node: Errprint150630 -Node: Location151849 -Node: M4exit154651 -Node: Frozen files156738 -Node: Using frozen files157519 -Node: Frozen file format160759 -Node: Compatibility163822 -Node: Extensions164437 -Node: Incompatibilities168204 -Node: Other Incompatibilities176116 -Node: Answers178044 -Node: Improved exch178661 -Node: Improved forloop179199 -Node: Improved foreach181035 -Node: Improved cleardivert187974 -Node: Improved fatal_error188957 -Node: Copying This Manual190019 -Node: GNU Free Documentation License190275 -Node: Indices212669 -Node: Concept index212949 -Node: Macro index224692 - -End Tag Table diff --git a/src/bin/m4/doc/m4.texinfo b/src/bin/m4/doc/m4.texinfo deleted file mode 100644 index b886565480..0000000000 --- a/src/bin/m4/doc/m4.texinfo +++ /dev/null @@ -1,6026 +0,0 @@ -\input texinfo @c -*- texinfo -*- -@comment ======================================================== -@comment %**start of header -@setfilename m4.info -@settitle GNU M4 macro processor -@setchapternewpage odd -@ifnothtml -@setcontentsaftertitlepage -@end ifnothtml -@finalout - -@include version.texi - -@c @tabchar{} -@c ---------- -@c The testsuite expects literal tab output in some examples, but -@c literal tabs in texinfo lead to formatting issues. -@macro tabchar -@ @c -@end macro - -@c @ovar{ARG} -@c ------------------- -@c The ARG is an optional argument. To be used for macro arguments in -@c their documentation. -@macro ovar{varname} -@r{[}@var{\varname\}@r{]} -@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. -@macro dvar{varname, default} -@r{[}@var{\varname\} = @samp{\default\}@r{]} -@end macro - -@comment %**end of header -@comment ======================================================== - -@copying - -This manual is for @acronym{GNU} M4 (version @value{VERSION}, @value{UPDATED}), -a package containing an implementation of the m4 macro language. - -Copyright @copyright{} 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, -2006 Free Software Foundation, Inc. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the @acronym{GNU} Free Documentation License, -Version 1.2 or any later version published by the Free Software -Foundation; with no Invariant Sections, no Front-Cover Texts, and no -Back-Cover Texts. A copy of the license is included in the section -entitled ``@acronym{GNU} Free Documentation License.'' -@end quotation -@end copying - -@dircategory GNU programming tools -@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 - -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@contents - -@ifnottex -@node Top -@top GNU M4 -@insertcopying -@end ifnottex - -@acronym{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 -@acronym{GNU} @code{m4} for generating @file{configure} scripts, but not for -running them. - -@acronym{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 @acronym{GNU} M4 -distribution. - -This is release @value{VERSION}. It is now considered stable: future -releases in the 1.4.x series are only meant to fix bugs, increase speed, -or improve documentation. However@dots{} - -An experimental feature, which would improve @code{m4} usefulness, -allows for changing the syntax for what is a @dfn{word} in @code{m4}. -You should use: -@comment ignore -@example -./configure --enable-changeword -@end example -@noindent -if you want this feature compiled in. The current implementation -slows down @code{m4} considerably and is hardly acceptable. In the -future, @code{m4} 2.0 will come with a different set of new features -that provide similar capabilities, but without the inefficiencies, so -changeword will go away and @emph{you should not count on it}. - -@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 - -* 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 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 - -How to invoke macros - -* Invocation:: Macro invocation -* Inhibiting Invocation:: Preventing macro invocation -* Macro Arguments:: Macro arguments -* Quoting Arguments:: On Quoting Arguments to macros -* Macro expansion:: Expanding macros - -How to define new macros - -* Define:: Defining a new macro -* Arguments:: Arguments to macros -* Pseudo Arguments:: Special arguments to macros -* Undefine:: Deleting a macro -* Defn:: Renaming macros -* Pushdef:: Temporarily redefining macros - -* Indir:: Indirect call of macros -* Builtin:: Indirect call of builtins - -Conditionals, loops, and recursion - -* Ifdef:: Testing if a macro is defined -* Ifelse:: If-else construct, or multibranch -* Shift:: Recursion in @code{m4} -* Forloop:: Iteration by counting -* Foreach:: Iteration by list contents - -How to debug macros and input - -* Dumpdef:: Displaying macro definitions -* Trace:: Tracing macro calls -* Debug Levels:: Controlling debugging output -* Debug Output:: Saving debugging output - -Input control - -* Dnl:: Deleting whitespace in input -* Changequote:: Changing the quote characters -* Changecom:: Changing the comment delimiters -* Changeword:: Changing the lexical structure of words -* M4wrap:: Saving text until end of input - -File inclusion - -* Include:: Including named files -* Search Path:: Searching for include files - -Diverting and undiverting output - -* Divert:: Diverting output -* Undivert:: Undiverting output -* Divnum:: Diversion numbers -* Cleardivert:: Discarding diverted text - -Macros for text handling - -* Len:: Calculating length of strings -* Index macro:: Searching for substrings -* Regexp:: Searching for regular expressions -* Substr:: Extracting substrings -* Translit:: Translating characters -* Patsubst:: Substituting text by regular expression -* Format:: Formatting strings (printf-like) - -Macros for doing arithmetic - -* Incr:: Decrement and increment operators -* Eval:: Evaluating integer expressions - -Macros for running shell commands - -* Platform macros:: Determining the platform -* Syscmd:: Executing simple commands -* Esyscmd:: Reading the output of commands -* Sysval:: Exit status -* Mkstemp:: Making temporary files - -Miscellaneous builtin macros - -* Errprint:: Printing error messages -* Location:: Printing current location -* M4exit:: Exiting from @code{m4} - -Fast loading of frozen state - -* Using frozen files:: Using frozen files -* Frozen file format:: Frozen file format - -Compatibility with other versions of @code{m4} - -* Extensions:: Extensions in @acronym{GNU} M4 -* Incompatibilities:: Facilities in System V m4 not in GNU M4 -* Other Incompatibilities:: Other incompatibilities - -Correct version of some examples - -* Improved exch:: Solution for @code{exch} -* Improved forloop:: Solution for @code{forloop} -* Improved foreach:: Solution for @code{foreach} -* Improved cleardivert:: Solution for @code{cleardivert} -* Improved fatal_error:: Solution for @code{fatal_error} - -How to make copies of this manual - -* GNU Free Documentation License:: License for copying this manual - -Indices of concepts and macros - -* Concept index:: Index for many concepts -* Macro index:: Index for all @code{m4} macros - -@end detailmenu -@end menu - -@node Preliminaries -@chapter Introduction and preliminaries - -This first chapter explains what @acronym{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. - -@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} - -@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 @acronym{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 @acronym{GNU} Autoconf, which requires @acronym{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}. @acronym{GNU} @code{m4} is mostly compatible with the -System V, Release 3 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 - -@code{GPM} was an important ancestor of @code{m4}. See -C. Stratchey: ``A General Purpose Macro generator'', Computer Journal -8,3 (1965), pp. 225 ff. @code{GPM} is also succinctly described into -David Gries classic ``Compiler Construction for Digital Computers''. - -The classic B. Kernighan and P.J. Plauger: ``Software Tools'', -Addison-Wesley, Inc. (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}, as described in ``The M4 Macro Processor'', Bell -Laboratories (1977). 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 frontend for @code{Ratfor}, @code{C} and @code{Cobol}. - -Ren@'e Seindal released his implementation of @code{m4}, @acronym{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 @acronym{GNU} @code{m4} in -1992, until 1994 when he released @acronym{GNU} @code{m4} 1.4, which was -the stable release for 10 years. It was at this time that @acronym{GNU} -Autoconf decided to require @acronym{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 @acronym{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. - -Meanwhile, development has continued on new features for @code{m4}, such -as dynamic module loading and additional builtins. When complete, -@acronym{GNU} @code{m4} 2.0 will start a new series of releases. - -@node Bugs -@section Problems and bugs - -If you have problems with @acronym{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 (Internet) -@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}. Also provide details about the platform you are -executing on. - -Non-bug suggestions are always welcome as well. If you have questions -about things that are unclear in the documentation or are just obscure -features, please report them too. - -@node Manual -@section Using this manual - -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{}}. Thus - -@comment ignore -@example -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 majority of these examples are self-contained, and you can run them -with similar results by invoking @kbd{m4 -d}. In fact, the testsuite -that is bundled in the @acronym{GNU} M4 package consists of the examples -in this document! - -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 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. 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 - -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} - -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. @acronym{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 -d+f -- ./a}, 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 -E -@itemx --fatal-warnings -Stop execution and exit @code{m4} once the first warning has been -issued, considering all of them to be fatal. - -@item -i -@itemx --interactive -@itemx -e -Makes this invocation of @code{m4} interactive. This means that all -output will be unbuffered, and interrupts will be ignored. 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 @acronym{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{m4___file__} -instead of @samp{__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. - -@item -W @var{REGEXP} -@itemx --word-regexp=@var{REGEXP} -Use @var{REGEXP} as an alternative syntax for macro names. This -experimental option will not be present in all @acronym{GNU} @code{m4} -implementations (@pxref{Changeword}). -@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 -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 -D @var{NAME}@r{[}=@var{VALUE}@r{]} -@itemx --define=@var{NAME}@r{[}=@var{VALUE}@r{]} -This enters @var{NAME} into the symbol table, before any input files are -read. 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 -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 -s -@itemx --synclines -Generate synchronization lines, for use by the C preprocessor or other -similar tools. Order is significant with respect to file names. This -option is useful, for example, when @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 beginning of the next generated line. - -@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 @acronym{GNU} -@code{m4}. - -@table @code -@item -G -@itemx --traditional -Suppress all the extensions made in this implementation, compared to the -System V version. @xref{Compatibility}, for a list of these. - -@item -H @var{NUM} -@itemx --hashsize=@var{NUM} -Make the internal hash table for symbol lookup be @var{NUM} entries big. -For better performance, the number should be prime, but this is not -checked. The default is 509 entries. It should not be necessary to -increase this value, unless you define an excessive number of macros. - -@item -L @var{NUM} -@itemx --nesting-limit=@var{NUM} -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. - -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. - -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 @acronym{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 -B @var{NUM} -@itemx -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. - -@item -N @var{NUM} -@itemx --diversions=@var{NUM} -These options are present only for compatibility with previous -versions of @acronym{GNU} @code{m4}, and were controlling the number of -possible diversions which could be used at the same time. They do nothing, -because there is no fixed limit anymore. They may disappear in future -releases, and issue a warning to that effect. -@end table - -@node Frozen state -@section Command line options for frozen state - -@acronym{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}, and -@option{-t} 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{[}@var{FLAGS}@r{]} -@itemx --debug@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{Debug Levels}, for more details on the format and -meaning of @var{FLAGS}. If omitted, @var{FLAGS} defaults to @samp{aeq}. - -@item --debugfile=@var{FILE} -@itemx -o @var{FILE} -@itemx --error-output=@var{FILE} -Redirect @code{dumpdef} output, debug messages, and trace output to the -named @var{FILE}. Warnings, error messages, and @code{errprint} output -are still printed to standard error. If unspecified, debug output goes -to standard error; if empty, debug output is discarded. @xref{Debug -Output}, for more details. The spellings @option{-o} and -@option{--error-output} are misleading and inconsistent with other -@acronym{GNU} tools; for now they are silently accepted as synonyms of -@option{--debugfile}, but in a future version of M4, using them will -cause a warning to be issued. - -@item -l @var{NUM} -@itemx --arglength=@var{NUM} -Restrict the size of the output generated by macro tracing to @var{NUM} -characters per trace line. If unspecified or zero, output is -unlimited. @xref{Debug Levels}, for more details. - -@item -t @var{NAME} -@itemx --trace=@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. -@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. If no names are present, standard input is read. A file -name of @file{-} is taken to mean standard input. It is -conventional, but not required, for input files to end in @samp{.m4}. - -The input files are read 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. - -The options @option{--define} (@option{-D}), @option{--undefine} -(@option{-U}), @option{--synclines} (@option{-s}), and @option{--trace} -(@option{-t}) only take effect after processing input from any file -names that occur earlier on the command line. - -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. - -@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. @acronym{GNU} @code{m4} does not yet understand -locales; all operations are byte-oriented rather than -character-oriented. 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'}). - -@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 -@end menu - -@node Names -@section Macro names - -@cindex names -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}. - -@node Quoted strings -@section Quoting input to @code{m4} - -@cindex quoted string -A quoted string is a sequence of characters surrounded by quote -strings, defaulting to -@samp{`} and @samp{'}, 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 macro -@code{changequote}. @xref{Changequote}, for more information. - -@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---comments are @emph{not} discarded by @code{m4}. - -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 -`quoted text' # `commented text' -@result{}quoted text # `commented text' -`quoting inhibits' `#' `comments' -@result{}quoting inhibits # comments -@end example - -The comment delimiters can be changed to any string at any time, using -the builtin macro @code{changecom}. @xref{Changecom}, for more -information. - -@node Other tokens -@section Other kinds of input tokens - -Any character, that is neither a part of a name, nor of a quoted string, -nor a comment, is a token by itself. When not in the context of macro -expansion, all of these tokens are just copied to output. However, -during macro expansion, whitespace characters (space, tab, newline, -formfeed, carriage return, vertical tab), parentheses (@samp{(} and -@samp{)}), comma (@samp{,}), and dollar (@samp{$}) have additional -roles, explained later. - -@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. 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 - -The order in which @code{m4} expands the macros can be explored using -the trace facilities of @acronym{GNU} @code{m4} (@pxref{Trace}). - -This process continues until there are no more macro calls to expand and -all the input has been consumed. - -@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 -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 Stratchey's @code{GPM}, for example), is the ability -to recognize macro calls without resorting to any special, prefixed -invocation character. While generally useful, this feature might -sometimes be the source of spurious, unwanted macro calls. So, @acronym{GNU} -@code{m4} offers several mechanisms or techniques for inhibiting the -recognition of names as macro calls. - -First of all, many builtin macros cannot meaningfully be called -without arguments. 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. - -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. - -Another alternative is to redefine problematic macros to a name less -likely to cause conflicts, @xref{Definitions}. - -If your version of @acronym{GNU} @code{m4} has the @code{changeword} feature -compiled in, it offers far more flexibility in specifying the -syntax of macro names, both builtin or user-defined. @xref{Changeword}, -for more information on this experimental feature. - -Of course, the simplest way to prevent a name from being interpreted -as a call to an existing macro is to quote it. The remainder of -this section studies a little more deeply how quoting affects macro -invocation, and how quoting can be used to inhibit macro invocation. - -Even if quoting is usually done over the whole macro name, it can also -be done over only a few characters of this name (provided, of course, -that the unquoted portions are not also a macro). It is also possible -to quote the empty string, but this works only @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. - -The output of macro evaluations is always rescanned. The following -example would yield the string @samp{de}, exactly as if @code{m4} -has been given @w{@samp{substr(`abcde', `3', `2')}} as input: - -@example -define(`x', `substr(ab') -@result{} -define(`y', `cde, `3', `2')') -@result{} -x`'y -@result{}de -@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 occuring 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 - -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. - -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. - -@example -hello world -@result{}hello world -define( -^D -@error{}m4:stdin:2: ERROR: 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 - -It is, however, in certain cases necessary or convenient 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. 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{changeword} (@pxref{Changeword}). - -@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 ignore -@example -foo -@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 - -* Indir:: Indirect call of macros -* Builtin:: Indirect call of builtins -@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 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 - -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 @acronym{GNU} extensions -@acronym{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 @acronym{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 this trick. - -@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 @code{%d} to @code{%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. It simply exchanges the order of the two arguments. - -@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 @acronym{GNU} extensions -@acronym{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. - -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. Thus, a macro to display the number of arguments -given can be - -@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 - -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 - -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 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. - -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 - -It is not an error for @var{name} to have no macro definition. In that -case, @code{undefine} does nothing. - -@node Defn -@section Renaming macros - -@cindex macros, how to rename -@cindex renaming macros -It is possible to rename an already defined macro. To do this, you need -the builtin @code{defn}: - -@deffn Builtin defn (@var{name}) -Expands to the @emph{quoted definition} of @var{name}. If the -argument is not a defined macro, the expansion is void. - -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 is only meaningful as the second argument to -@code{define} (and @code{pushdef}), and is silently converted to an -empty string in most 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 - -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 - -Using @code{defn} to generate special tokens for builtin macros outside -of expected contexts can sometimes trigger warnings. But most of the -time, such tokens are silently converted to the empty string. - -@example -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 -@end example - -@node Pushdef -@section Temporarily redefining macros - -@cindex macros, temporary redefinition of -@cindex temporary redefinition of macros -@cindex redefinition of macros, temporary -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 pushdef (@var{name}, @ovar{expansion}) -@deffnx Builtin 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}. - -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. - -@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}. - -@node Indir -@section Indirect call of macros - -@cindex indirect call of macros -@cindex call of macros, indirect -@cindex macros, indirect call of -@cindex @acronym{GNU} extensions -Any macro can be called indirectly with @code{indir}: - -@deffn Builtin 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, an -error message is printed, and the expansion is void. - -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 -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: undefined macro `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 -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: empty string treated as 0 in builtin `divert' -@result{} -@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 @acronym{GNU} extensions -Builtin macros can be called indirectly with @code{builtin}: - -@deffn Builtin builtin (@var{name}, @ovar{args@dots{}}) -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, an error message is printed, and the expansion is void. - -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. - -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 result in a void expansion. - -@example -builtin -@result{}builtin -builtin() -@error{}m4:stdin:2: undefined builtin `' -@result{} -builtin(`builtin') -@error{}m4:stdin:3: Warning: too few arguments to builtin `builtin' -@result{} -builtin(`builtin',) -@error{}m4:stdin:4: undefined builtin `' -@result{} -@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 -@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 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: excess arguments to builtin `ifdef' ignored -@result{}no -@end example - -@node Ifelse -@section If-else construct, or multibranch - -@cindex comparing strings -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 ifelse (@var{comment}) -@deffnx Builtin ifelse (@var{string-1}, @var{string-2}, @var{equal}, @ - @ovar{not-equal}) -@deffnx Builtin ifelse (@var{string-1}, @var{string-2}, @var{equal-1}, @ - @var{string-3}, @var{string-4}, @var{equal-2}, @dots{}) -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 @acronym{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: too few arguments to builtin `ifelse' -@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 - -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 many of the 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 - -@cindex multibranches -However, @code{ifelse} can take more than four arguments. If given more -than four arguments, @code{ifelse} works like a @code{case} or @code{switch} -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: excess arguments to builtin `ifelse' ignored -@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: excess arguments to builtin `ifelse' ignored -@result{}7 -@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 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: - -@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{$@@}. Sometimes, a -recursive algorithm requires adding quotes to each 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}/@/examples/@/quote.m4} in this package. First, -let's examine their usage: - -@example -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 distinquish -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. - -@example -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 - -@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: - -@example -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: - -@example -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}/@/examples/@/forloop.m4} in this package: - -@example -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}/@/examples/@/foreach.m4}, and @code{foreachq} -in @file{m4-@value{VERSION}/@/examples/@/foreachq.m4}. - -@example -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: - -@example -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}: - -@example -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: - -@example -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: - -@example -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}). (It is possible to have robust iteration with linear -behavior 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 Debugging -@chapter How to debug macros and input - -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 -* Debug Levels:: Controlling debugging output -* Debug Output:: Saving debugging output -@end menu - -@node Dumpdef -@section Displaying macro definitions - -@cindex displaying macro definitions -@cindex macros, displaying definitions -@cindex definitions, displaying macro -If you want to see what a name expands into, you can use the builtin -@code{dumpdef}: - -@deffn Builtin dumpdef (@ovar{names@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 the @var{names} given. The output is printed to the -current debug file (usually standard error), and is sorted by name. If -an unknown name is encountered, a warning is printed. - -The expansion of @code{dumpdef} is void. -@end deffn - -@example -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 -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: undefined macro `f' -@result{}f1 -@end example - -@xref{Debug Levels}, for information on controlling the details of the -display. - -@node Trace -@section Tracing macro calls - -@cindex tracing macro expansion -@cindex macro expansion, tracing -@cindex expansion, tracing macro -It is possible to trace macro calls and expansions through the builtins -@code{traceon} and @code{traceoff}: - -@deffn Builtin traceon (@ovar{names@dots{}}) -@deffnx Builtin traceoff (@ovar{names@dots{}}) -When called without any arguments, @code{traceon} and @code{traceoff} -will turn tracing on and off, respectively, for all defined macros. - -When called with arguments, only the macros listed in @var{names} are -affected, whether or not they are currently defined. - -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{Debug -Output}). - -@example -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} (@pxref{Limits control, , Invoking m4}). - -Tracing by name is an attribute that is preserved whether the macro is -defined or not. This allows the @option{-t} option to select macros to -trace before those macros are defined. - -@example -traceoff(`foo') -@result{} -traceon(`foo') -@result{} -foo -@result{}foo -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:8: undefined macro `foo' -@result{} -define(`foo', `blah') -@result{} -foo -@error{}m4trace: -1- foo -> `blah' -@result{}blah -traceoff -@result{} -foo -@result{}blah -@end example - -Tracing even works on builtins. However, @command{defn} (@pxref{Defn}) -does not transfer tracing status. - -@example -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 - -@xref{Debug Levels}, for information on controlling the details of the -display. - -@node Debug Levels -@section Controlling debugging output - -@cindex controlling debugging output -@cindex debugging output, controlling -The @option{-d} option to @code{m4} (@pxref{Debugging options, , -Invoking m4}) controls the amount of details presented, when using the -macros described in the preceding sections. - -The @var{flags} following the option can be one or more of the -following: - -@table @code -@item a -Show the actual arguments in each macro call. This applies to all macro -calls if the @samp{t} flag is used, otherwise only the macros covered by -calls of @code{traceon}. - -@item c -Show several trace lines for each macro call. A line is shown when the -macro is seen, but before the arguments are collected; a second line -when the arguments have been collected and a third line after the call -has completed. - -@item e -Show the expansion of each macro call, if it is not void. This applies -to all macro calls if the @samp{t} flag is used, otherwise only the -macros covered by calls of @code{traceon}. - -@item f -Show the name of the current input file in each trace output line. - -@item i -Print a message each time the current input file is changed, giving file -name and input line number. - -@item l -Show the current input line number in each trace output line. - -@item p -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 -Quote actual arguments and macro expansions in the display with the -current quotes. - -@item t -Trace all macro calls made in this invocation of @code{m4}. - -@item x -Add a unique `macro call id' to each line of the trace output. This is -useful in connection with the @samp{c} flag above. - -@item V -A shorthand for all of the above flags. -@end table - -If no flags are specified with the @option{-d} option, the default is -@samp{aeq}. The examples throughout this manual assume the default -flags. - -@cindex @acronym{GNU} extensions -There is a builtin macro @code{debugmode}, which allows on-the-fly control of -the debugging output format: - -@deffn Builtin debugmode (@ovar{flags}) -The argument @var{flags} should be a subset of the letters listed above. -As special cases, if the argument starts with a @samp{+}, the flags are -added to the current debug flags, and if it starts with a @samp{-}, they -are removed. If no argument is present, all debugging flags are cleared -(as if no @option{-d} was given), and with an empty argument the flags -are reset to the default of @samp{aeq}. - -The expansion of @code{debugmode} is void. -@end deffn - -@example -define(`foo', `FOO') -@result{} -traceon(`foo') -@result{} -debugmode() -@result{} -foo -@error{}m4trace: -1- foo -> `FOO' -@result{}FOO -debugmode -@result{} -foo -@error{}m4trace: -1- foo -@result{}FOO -debugmode(`+l') -@result{} -foo -@error{}m4trace:8: -1- foo -@result{}FOO -@end example - -@node Debug Output -@section Saving debugging output - -@cindex saving debugging output -@cindex debugging output, saving -@cindex output, saving debugging -@cindex @acronym{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 debugfile (@ovar{file}) -Sends 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. 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. - -The expansion of @code{debugfile} is void. -@end deffn - -@example -traceon(`divnum') -@result{} -divnum(`extra') -@error{}m4:stdin:2: Warning: excess arguments to builtin `divnum' ignored -@error{}m4trace: -1- divnum(`extra') -> `0' -@result{}0 -debugfile() -@result{} -divnum(`extra') -@error{}m4:stdin:4: Warning: excess arguments to builtin `divnum' ignored -@result{}0 -debugfile -@result{} -divnum -@error{}m4trace: -1- divnum -> `0' -@result{}0 -@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 -* Changeword:: Changing the lexical structure of words -* M4wrap:: Saving text until end of input -@end menu - -@node Dnl -@section Deleting whitespace in input - -@cindex deleting whitespace in input -The builtin @code{dnl} stands for ``Discard to Next Line'': - -@deffn Builtin dnl -All characters, up to and including the next newline, are discarded -without performing any macro expansion. A warning is issued if the end -of the file is encountered without a newline. - -The expansion of @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}). - -Usually, @code{dnl} is immediately followed by an end of line or some -other whitespace. @acronym{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: excess arguments to builtin `dnl' ignored -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: end of file treated as newline -@result{}0 HI 2 HI -@end example - -@node Changequote -@section Changing the quote characters - -@cindex changing the quote delimiters -@cindex quote delimiters, changing the -The default quote delimiters can be changed with the builtin -@code{changequote}: - -@deffn Builtin 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. -@ignore -@comment Yuck. I know of no clean way to render an 8-bit character in -@comment both info and dvi. This example uses the `open-guillemot' and -@comment `close-guillemot' characters of the Latin-1 character set. - -@example -define(`a', `b') -@result{} -«a» -@result{}«b» -changequote(`«', `»') -@result{} -«a» -@result{}a -@end example -@end ignore -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 @acronym{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{changeword} (@pxref{Changeword}), 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 - -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. - -@example -`hello world' -@result{}hello world -`dangling quote -^D -@error{}m4:stdin:2: ERROR: end of file in string -@end example - -@node Changecom -@section Changing the comment delimiters - -@cindex changing comment delimiters -@cindex comment delimiters, changing -The default comment delimiters can be changed with the builtin -macro @code{changecom}: - -@deffn Builtin 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. -@ignore -@comment Yuck. I know of no clean way to render an 8-bit character in -@comment both info and dvi. This example uses the `open-guillemot' and -@comment `close-guillemot' characters of the Latin-1 character set. - -@example -define(`a', `b') -@result{} -«a» -@result{}«b» -changecom(`«', `»') -@result{} -«a» -@result{}«a» -@end example -@end ignore -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 @acronym{GNU} has no inherent limit. - -Comments are recognized in preference to macros. However, this is not -compatible with other implementations, where macros and even quoting -takes precedence over comments, so it may change in a future release. -For portability, this means that @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 -@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: -echo((hi)) -@result{}0::((hi)) -changecom(`,', `)') -@result{} -echo(hi,hi)bye) -@result{}1:HI,hi)bye: -@end example - -It is an error if the end of file occurs within a comment. - -@example -changecom(`/*', `*/') -@result{} -/*dangling comment -^D -@error{}m4:stdin:2: ERROR: end of file in comment -@end example - -@node Changeword -@section Changing the lexical structure of words - -@cindex lexical structure of words -@cindex words, lexical structure of -@quotation -The macro @code{changeword} and all associated functionality is -experimental. It is only available if the @option{--enable-changeword} -option was given to @code{configure}, at @acronym{GNU} @code{m4} installation -time. The functionality will go away in the future, to be replaced by -other new features that are more efficient at providing the same -capabilities. @emph{Do not rely on it}. Please direct your comments -about it the same way you would do for bugs. -@end quotation - -A file being processed by @code{m4} is split into quoted strings, words -(potential macro names) and simple tokens (any other single character). -Initially a word is defined by the following regular expression: - -@comment ignore -@example -[_a-zA-Z][_a-zA-Z0-9]* -@end example - -Using @code{changeword}, you can change this regular expression: - -@deffn {Optional builtin} changeword (@var{regex}) -Changes the regular expression for recognizing macro names to be -@var{regex}. If @var{regex} is empty, use -@samp{[_a-zA-Z][_a-zA-Z0-9]*}. @var{regex} must obey the constraint -that every prefix of the desired final pattern is also accepted by the -regular expression. If @var{regex} contains grouping parentheses, the -macro invoked is the portion that matched the first group, rather than -the entire matching string. - -The expansion of @code{changeword} is void. -The macro @code{changeword} is recognized only with parameters. -@end deffn - -Relaxing the lexical rules of @code{m4} might be useful (for example) if -you wanted to apply translations to a file of numbers: - -@example -ifdef(`changeword', `', `errprint(` skipping: no changeword support -')m4exit(`77')')dnl -changeword(`[_a-zA-Z0-9]+') -@result{} -define(`1', `0')1 -@result{}0 -@end example - -Tightening the lexical rules is less useful, because it will generally -make some of the builtins unavailable. You could use it to prevent -accidental call of builtins, for example: - -@example -ifdef(`changeword', `', `errprint(` skipping: no changeword support -')m4exit(`77')')dnl -define(`_indir', defn(`indir')) -@result{} -changeword(`_[_a-zA-Z0-9]*') -@result{} -esyscmd(`foo') -@result{}esyscmd(foo) -_indir(`esyscmd', `echo hi') -@result{}hi -@result{} -@end example - -Because @code{m4} constructs its words a character at a time, there -is a restriction on the regular expressions that may be passed to -@code{changeword}. This is that if your regular expression accepts -@samp{foo}, it must also accept @samp{f} and @samp{fo}. - -@example -ifdef(`changeword', `', `errprint(` skipping: no changeword support -')m4exit(`77')')dnl -define(`foo -', `bar -') -@result{} -dnl This example wants to recognize changeword, dnl, and `foo\n'. -dnl First, we check that our regexp will match. -regexp(`changeword', `[cd][a-z]*\|foo[ -]') -@result{}0 -regexp(`foo -', `[cd][a-z]*\|foo[ -]') -@result{}0 -regexp(`f', `[cd][a-z]*\|foo[ -]') -@result{}-1 -foo -@result{}foo -changeword(`[cd][a-z]*\|foo[ -]') -@result{} -dnl Even though `foo\n' matches, we forgot to allow `f'. -foo -@result{}foo -changeword(`[cd][a-z]*\|fo*[ -]?') -@result{} -dnl Now we can call `foo\n'. -foo -@result{}bar -@end example - -@ignore -@comment One more test of including newline in a macro name; but this -@comment does not need to be displayed in the manual. This ensures -@comment that line numbering is correct when dnl cuts across include -@comment file boundaries, and when __file__ or __line__ is the last -@comment token in an include file. - -@example -ifdef(`changeword', `', `errprint(` skipping: no changeword support -')m4exit(`77')')dnl -define(`bar -', defn(`dnl'))dnl -define(`baz', `dnl -include(`foo') ignored -dnl')dnl -changeword(`\([_a-zA-Z][_a-zA-Z0-9]*\|bar -\)') -@result{} -__file__:__line__ -@result{}stdin:10 -include(`foo') ignored -__file__:__line__ -@result{}stdin:12 -baz ignored -__file__:__line__ -@result{}stdin:14 -define(`bar -', defn(`__file__')) -@result{} -include(`foo') -@result{}../examples/foo -define(`bar -', defn(`__line__')) -@result{} -include(`foo') -@result{}1 -__file__:__line__ -@result{}stdin:21 -@end example -@end ignore - -@code{changeword} has another function. If the regular expression -supplied contains any grouped subexpressions, then text outside -the first of these is discarded before symbol lookup. So: - -@example -ifdef(`changeword', `', `errprint(` skipping: no changeword support -')m4exit(`77')')dnl -ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics -')m4exit(`77')')dnl -changecom(`/*', `*/')dnl -define(`foo', `bar')dnl -changeword(`#\([_a-zA-Z0-9]*\)') -@result{} -#esyscmd(`echo foo \#foo') -@result{}foo bar -@result{} -@end example - -@code{m4} now requires a @samp{#} mark at the beginning of every -macro invocation, so one can use @code{m4} to preprocess plain -text without losing various words like @samp{divert}. - -In @code{m4}, macro substitution is based on text, while in @TeX{}, it -is based on tokens. @code{changeword} can throw this difference into -relief. For example, here is the same idea represented in @TeX{} and -@code{m4}. First, the @TeX{} version: - -@comment ignore -@example -\def\a@{\message@{Hello@}@} -\catcode`\@@=0 -\catcode`\\=12 -@@a -@@bye -@result{}Hello -@end example - -@noindent -Then, the @code{m4} version: - -@example -ifdef(`changeword', `', `errprint(` skipping: no changeword support -')m4exit(`77')')dnl -define(`a', `errprint(`Hello')')dnl -changeword(`@@\([_a-zA-Z0-9]*\)') -@result{} -@@a -@result{}errprint(Hello) -@end example - -In the @TeX{} example, the first line defines a macro @code{a} to -print the message @samp{Hello}. The second line defines @key{@@} to -be usable instead of @key{\} as an escape character. The third line -defines @key{\} to be a normal printing character, not an escape. -The fourth line invokes the macro @code{a}. So, when @TeX{} is run -on this file, it displays the message @samp{Hello}. - -When the @code{m4} example is passed through @code{m4}, it outputs -@samp{errprint(Hello)}. The reason for this is that @TeX{} does -lexical analysis of macro definition when the macro is @emph{defined}. -@code{m4} just stores the text, postponing the lexical analysis until -the macro is @emph{used}. - -You should note that using @code{changeword} will slow @code{m4} down -by a factor of about seven, once it is changed to something other -than the default regular expression. You can invoke @code{changeword} -with the empty string to restore the default word definition, and regain -the parsing speed. - -@node M4wrap -@section Saving text until end of input - -@cindex saving input -@cindex input, saving -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 m4wrap (@var{string}, @dots{}) -Stores @var{string} in a safe place, to be reread when end of input is -reached. As a @acronym{GNU} extension, additional arguments are -concatenated with a space to the @var{string}. - -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}. - -@comment FIXME: this contradicts POSIX, which requires that "If the -@comment m4wrap macro is used multiple times, the arguments specified -@comment shall be processed in the order in which the m4wrap macros were -@comment processed." -It is safe to call @code{m4wrap} from saved text, but then the order in -which the saved text is reread is undefined. If @code{m4wrap} is not used -recursively, the saved pieces of text are reread in the opposite order -in which they were saved (LIFO---last in, first out). However, this -behavior is likely to change in a future release, to match -@acronym{POSIX}, so you should not depend on this order. - -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(`aa', `AA -') -@result{} -m4wrap(`a')m4wrap(`a') -@result{} -^D -@result{}AA -@end example - -@noindent -however, the transition between recursion levels behaves like an end of -file condition between two input files. - -@example -m4wrap(`m4wrap(`)')len(abc') -@result{} -^D -@error{}m4:stdin:1: ERROR: end of file in argument list -@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 -* Search Path:: Searching for include files -@end menu - -@node Include -@section Including named files - -There are two builtin macros in @code{m4} for including files: - -@deffn Builtin include (@var{file}) -@deffnx Builtin 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 (or cannot 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 - -@example -include(`none') -@error{}m4:stdin:1: cannot open `none': No such file or directory -@result{} -include() -@error{}m4:stdin:2: cannot open `': No such file or directory -@result{} -sinclude(`none') -@result{} -sinclude() -@result{} -@end example - -The rest of this section assumes that @code{m4} is invoked with the -@option{-I} option (@pxref{Preprocessor features, , Invoking m4}) -pointing to the @file{m4-@value{VERSION}/@/examples} -directory shipped as part of the @acronym{GNU} @code{m4} package. The -file @file{m4-@value{VERSION}/@/examples/@/incl.m4} in the distribution -contains the lines: - -@comment ignore -@example -Include file start -foo -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: - -@example -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}: - -@example -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. @acronym{GNU} @code{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 @acronym{GNU} @code{m4}, an alternative method of reading files is -using @code{undivert} (@pxref{Undivert}) on a named file. - -@node Search Path -@section Searching for include files - -@cindex search path for included files -@cindex included files, search path for -@cindex @acronym{GNU} extensions -@acronym{GNU} @code{m4} allows included files to be found in other directories -than the current working directory. - -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{Debug Levels}) can help isolate the problem. - -@node Diversions -@chapter Diverting and undiverting 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. - -Numbered diversions are counted from 0 upwards, diversion number 0 -being the normal output stream. The number of simultaneous diversions -is limited mainly by the memory used to describe them, because @acronym{GNU} -@code{m4} tries to keep diversions in memory. However, there is a -limit to the overall memory usable by all diversions taken altogether -(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}. -So, it is theoretically possible that the number and aggregate size of -diversions is limited only by available disk space. - -@ignore -@comment We need to test spilled diversions, but don't need to expose -@comment this highly repetitive test in the manual. - -@example -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`'dnl -len(f) -@result{}1048576 -divert(`1') -f -divert(`-1')undivert -@end example - -@comment Another test of spilled diversions. - -@example -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`'dnl -len(f) -@result{}1048576 -divert(`1') -f -m4exit -@end example -@end ignore - -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, @acronym{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 divert (@dvar{number, 0}) -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. - -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 preceeds ') -@result{} -^D -@result{}Wrapped TEXT preceeds diverted text. -@end example - -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 @acronym{GNU} extensions -Traditional implementations only supported ten diversions. But as a -@acronym{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 - -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 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. - -As a @acronym{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{} -@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(`2')undivert`'dnl -divert`'undivert`'dnl -@result{}two -@result{}one -@result{}three -@end example - -@cindex @acronym{GNU} extensions -@cindex file inclusion -@cindex inclusion, of files -@acronym{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, the file -@file{m4-@value{VERSION}/@/examples/@/foo} contains the word @samp{bar}: - -@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. - -@node Divnum -@section Diversion numbers - -@cindex diversion numbers -The current diversion is tracked by the builtin @code{divnum}: - -@deffn Builtin 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 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 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 - -Searching for substrings is done with @code{index}: - -@deffn Builtin index (@var{string}, @var{substring}) -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}. - -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. - -@example -index(`abc') -@error{}m4:stdin:1: Warning: too few arguments to builtin `index' -@result{}0 -@end example - -@node Regexp -@section Searching for regular expressions - -@cindex regular expressions -@cindex @acronym{GNU} extensions -Searching for regular expressions is done with the builtin -@code{regexp}: - -@deffn Builtin regexp (@var{string}, @var{regexp}, @ovar{replacement}) -Searches for @var{regexp} in @var{string}. The syntax for regular -expressions is the same as in @acronym{GNU} Emacs. -@ifnothtml -@xref{Regexps, , Syntax of Regular Expressions, emacs, The GNU Emacs -Manual}. -@end ifnothtml -@ifhtml -See -@uref{http://www.gnu.org/@/software/@/emacs/@/manual/@/emacs.html#Regexps, -Syntax of Regular Expressions} in the @acronym{GNU} Emacs Manual. -@end ifhtml - -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', `\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. - -@ignore -@comment No need to fight 8-bit characters, as it is difficult to get -@comment rendering right in both info and dvi. - -@example -translit(`«abc~', `~-»') -@result{}abc -@end example -@end ignore - -Omitting @var{chars} evokes a warning, but still produces output. - -@example -translit(`abc') -@error{}m4:stdin:1: Warning: too few arguments to builtin `translit' -@result{}abc -@end example - -@node Patsubst -@section Substituting text by regular expression - -@cindex regular expressions -@cindex pattern substitution -@cindex substitution by regular expression -@cindex @acronym{GNU} extensions -Global substitution in a string is done by @code{patsubst}: - -@deffn Builtin patsubst (@var{string}, @var{regexp}, @ovar{replacement}) -Searches @var{string} for matches of @var{regexp}, and substitutes -@var{replacement} for each match. The syntax for regular expressions -is the same as in @acronym{GNU} Emacs (@pxref{Regexp}). - -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 - -@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: trailing \ ignored in replacement -@result{}GNUs NOT Unix -@end example - -Here is a slightly more realistic example, which capitalizes individual -word 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 - -@example -define(`upcase', `translit(`$*', `a-z', `A-Z')')dnl -define(`downcase', `translit(`$*', `A-Z', `a-z')')dnl -define(`capitalize1', - `regexp(`$1', `^\(\w\)\(\w*\)', - `upcase(`\1')`'downcase(`\2')')')dnl -define(`capitalize', - `patsubst(`$1', `\w+', `capitalize1(`\&')')')dnl -capitalize(`GNUs not Unix') -@result{}Gnus Not Unix -@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. - -@example -patsubst(`abc') -@error{}m4:stdin:1: Warning: too few arguments to builtin `patsubst' -@result{}abc -@end example - -@node Format -@section Formatted output - -@cindex formatted output -@cindex output, formatted -@cindex @acronym{GNU} extensions -Formatted output can be made with @code{format}: - -@deffn Builtin 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: - -@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(`%.0f', `56789.9876') -@result{}56790 -len(format(`%-*X', `300', `1')) -@result{}300 -@end example - -Using the @code{forloop} macro defined earlier (@pxref{Forloop}), this -example shows how @code{format} can be used to produce tabular output. - -@example -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{e}, -@samp{E}, @samp{f}, @samp{F}, @samp{g}, @samp{G}, and @samp{%}; it -supports field widths and precisions, and the -modifiers @samp{+}, @samp{-}, @samp{@w{ }}, @samp{0}, @samp{#}, @samp{h} and -@samp{l}. For more details on the functioning of @code{printf}, see the -C Library Manual. - -For now, unrecognized specifiers are silently ignored, but it is -anticipated that a future release of @acronym{GNU} @code{m4} will support more -specifiers, and give warnings when problems are encountered. Likewise, -escape sequences are not yet recognized. - -@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 -@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 incr (@var{number}) -@deffnx Builtin 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: empty string treated as 0 in builtin `incr' -@result{}1 -decr() -@error{}m4:stdin:4: empty string treated as 0 in builtin `decr' -@result{}-1 -@end example - -@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 eval (@var{expression}, @dvar{radix, 10}, @ovar{width}) -Expands to the value of @var{expression}. The expansion is empty -if an error is encountered while parsing the arguments. If specified, -@var{radix} and @var{width} control the format of the output. - -The macro @code{eval} is recognized only with parameters. -@end deffn - -Expressions can contain the following operators, listed in order of -decreasing precedence. - -@table @code -@item + - -Unary plus and minus -@item ** -Exponentiation -@item * / % -Multiplication, division and modulo -@item + - -Addition and subtraction -@item << >> -Shift left or right -@item == != > >= < <= -Relational operators -@item ! -Logical negation -@item ~ -Bitwise negation -@item & -Bitwise and -@item ^ -Bitwise exclusive-or -@item | -Bitwise or -@item && -Logical and -@item || -Logical or -@end table - -All operators, except exponentiation, are left associative. - -Note that some older @code{m4} implementations use @samp{^} as an -alternate operator for exponentiation, although @acronym{POSIX} requires -the C behavior of bitwise exclusive-or. On the other hand, the -precedence of @samp{~} and @samp{!} are different in @acronym{GNU} -@code{m4} than -they are in C, matching the precedence in traditional @code{m4} -implementations. This behavior is likely to change in a future -version to match @acronym{POSIX}, so use parentheses to force the -desired precedence. - -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. @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(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:8: bad expression in eval: 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}. - -All evaluation is done with 32-bit signed integers, assuming -2's-complement with wrap-around. The shift operators are defined in -@acronym{GNU} -@code{m4} by doing an implicit bit-wise and of the right-hand operand -with 0x1f, and sign-extension with right shift. - -@example -eval(0x80000000 / -1) -@result{}-2147483648 -eval(0x80000000 % -1) -@result{}0 -eval(0x7fffffff) -@result{}2147483647 -incr(eval(0x7fffffff)) -@result{}-2147483648 -eval(-4 >> 33) -@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. It is an error 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. 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. -It is an error if the width is negative. On error, 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 -@end example - -@node Shell commands -@chapter Macros for running shell commands - -@cindex executing UNIX commands -@cindex running UNIX commands -@cindex UNIX commands, running -@cindex commands, running UNIX -@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 @code{/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 -@code{/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 -@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. @acronym{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__ -@deffnx {Optional builtin} __os2__ -@deffnx {Optional builtin} os2 -@deffnx {Optional builtin} __unix__ -@deffnx {Optional builtin} unix -@deffnx {Optional builtin} __windows__ -@deffnx {Optional builtin} 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 - -When @acronym{GNU} extensions are in effect (that is, when you did not -use the @option{-G} option, @pxref{Limits control, , Invoking m4}), -@acronym{GNU} @code{m4} will define the macro @code{@w{__gnu__}} to -expand to the empty string. - -@example -__gnu__ -@result{} -ifdef(`__gnu__', `Extensions are active') -@result{}Extensions are active -@end example - -@cindex platform macro -On UNIX systems, @acronym{GNU} @code{m4} will define @code{@w{__unix__}} -by default, or @code{unix} when the @option{-G} option is specified. - -On native Windows systems, @acronym{GNU} @code{m4} will define -@code{@w{__windows__}} by default, or @code{windows} when the -@option{-G} option is specified. - -On OS/2 systems, @acronym{GNU} @code{m4} will define @code{@w{__os2__}} -by default, or @code{os2} when the @option{-G} option is specified. - -If @acronym{GNU} @code{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 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}. - -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. - -As an example of @var{shell-command} using the same standard input as -@code{m4}, the command line @kbd{echo "m4wrap(\`syscmd(\`cat')')" | m4} -will tell @code{m4} to read all of its input before executing the -wrapped text, then hand 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. - -@ignore -@comment If the user types the example below with stdin being an -@comment interactive terminal, then cat will hang waiting for additional -@comment input after m4 has exited. But the testsuite is using a pipe -@comment for stdin. Hence, we have two versions - the one we feed the -@comment testsuite below, and the one we display to the user above that -@comment more accurately shows what the testsuite is really doing but -@comment which the testsuite cannot parse. - -@example -m4wrap(`syscmd(`cat')') -@result{} -^D -@end example -@end ignore - -@node Esyscmd -@section Reading the output of commands - -@cindex @acronym{GNU} extensions -If you want @code{m4} to read the output of a shell command, use -@code{esyscmd}: - -@deffn Builtin 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}. - -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}. - -@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 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 -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(`exit 2') -@result{} -sysval -@result{}2 -esyscmd(`true') -@result{} -sysval -@result{}0 -@end example - -@command{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. - -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 That leaves KILL and PIPE as the two signals tested. -@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 -13 $$') -@result{} -sysval -@result{}3328 -esyscmd(`kill -9 $$') -@result{} -sysval -@result{}2304 -@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 mkstemp (@var{template}) -@deffnx Builtin maketemp (@var{template}) -Expands to a 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 @acronym{POSIX}, is that -@code{maketemp} merely replaces the trailing @samp{X} with the process -id, without creating a file, 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, @acronym{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 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 -maketemp(`/tmp/fooXXXXXX') -@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 - -@cindex @acronym{GNU} extensions -Unless you use the @option{--traditional} command line option (or -@option{-G}, @pxref{Limits control, , Invoking m4}), the @acronym{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 -@acronym{GNU} M4 1.4.8, which is secure even in traditional mode. - -@example -syscmd(`echo foo??????')dnl -@result{}foo?????? -define(`file1', maketemp(`fooXXXXXX'))dnl -ifelse(esyscmd(`echo foo??????'), `foo??????', `no file', `created') -@result{}created -define(`file2', maketemp(`fooXX'))dnl -define(`file3', mkstemp(`fooXXXXXX'))dnl -ifelse(len(file1), len(file2), `same length', `different') -@result{}same length -ifelse(file1, file2, `same', `different file') -@result{}different file -ifelse(file2, file3, `same', `different file') -@result{}different file -ifelse(file1, file3, `same', `different file') -@result{}different file -syscmd(`rm 'file1 file2 file3) -@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} -@end menu - -@node Errprint -@section Printing error messages - -@cindex printing error messages -@cindex error messages, printing -@cindex messages, printing error -You can print error messages using @code{errprint}: - -@deffn Builtin 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: @acronym{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 @acronym{POSIX} is silent on whether this is acceptable. - -@node Location -@section Printing current location - -To make it possible to specify the location of an error, three -utility builtins exist: - -@deffn Builtin __file__ -@deffnx Builtin __line__ -@deffnx Builtin __program__ -Expand to the quoted name of the current input file, the -current input line number in that file, and the quoted name of the -current invocation of @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. The syncline option (@option{-s}, -@pxref{Preprocessor features, , Invoking m4}), and the -@samp{f} and @samp{l} flags of @code{debugmode} (@pxref{Debug Levels}), -also use this notion of current file and line. Redefining the three -location macros has no effect on syncline, debug, or warning message -output. Assume this example is run in the -@file{m4-@value{VERSION}/@/checks} directory of the @acronym{GNU} M4 -package, using @samp{--include=../examples} in the command line to find -the file @file{incl.m4} mentioned earlier: - -@example -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 ../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 @acronym{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 -^D -@result{}6 -@result{}6 -@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 -@acronym{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 m4exit (@dvar{code, 0}) -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 - -@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, e.g., 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 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. @acronym{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:: Frozen file format -@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 states -@cindex dumping into frozen file -@cindex reloading a frozen file -@cindex @acronym{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 -m4 base.m4 input1.m4 -m4 base.m4 input2.m4 -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 -m4 -F base.m4f base.m4 -@end example - -@noindent -once, and further execute, as often as needed: - -@comment ignore -@example -m4 -R base.m4f input1.m4 -m4 -R base.m4f input2.m4 -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, @acronym{GNU} -@code{m4} produces on @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 -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 -m4 -F file1.m4f file1.m4 -m4 -R file1.m4f -F file2.m4f file2.m4 -m4 -R file2.m4f -F file3.m4f file3.m4 -m4 -R file3.m4f file4.m4 -@end example - -Some care is necessary because not every effort has been made for -this to work in all cases. In particular, the trace attribute of -macros is not handled, nor the current setting of @code{changeword}. -Currently, @code{m4wrap} and @code{sysval} also have problems. -Also, interactions for some options of @code{m4}, being used in one call -and not in the next, have not been fully analyzed yet. On the other -end, you may be confident that stacks of @code{pushdef} definitions -are handled correctly, as well as undefined or renamed builtins, and -changed strings for quotes or comments. And future releases of -@acronym{GNU} M4 will improve on the utility 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 -@section Frozen file format -@cindex frozen file format -@cindex file format, frozen file -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 @acronym{GNU} @code{m4}. -It is conventional, but not required, to give a frozen file the suffix -of @code{.m4f}. - -These are simple (editable) text files, made up of directives, -each starting with a capital letter and ending with a newline -(@key{NL}). Wherever a directive is expected, the character -@samp{#} introduces 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 -the corresponding strings @var{str} in the next line of input. Numbers -are always expressed in decimal. There are no escape characters. The -directives are: - -@table @code -@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 non-existing diversion. 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. @acronym{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 changeword support, but the version -of @code{m4} reloading was compiled without it), 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. - -@item V @var{number} @key{NL} -Confirms the format of the file. @code{m4} @value{VERSION} only creates -and understands frozen files where @var{number} is 1. This directive -must be the first non-comment in the file, and may not appear more than -once. -@end table - -@node Compatibility -@chapter Compatibility with other versions of @code{m4} - -@cindex compatibility -This chapter describes the differences between this implementation of -@code{m4}, and the implementation found under UNIX, notably System V, -Release 3. - -There are also differences in BSD flavors of @code{m4}. No attempt -is made to summarize these here. - -@menu -* Extensions:: Extensions in @acronym{GNU} M4 -* Incompatibilities:: Facilities in System V m4 not in GNU M4 -* Other Incompatibilities:: Other incompatibilities -@end menu - -@node Extensions -@section Extensions in @acronym{GNU} @code{m4} - -@cindex @acronym{GNU} extensions -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 (@pxref{Limits control, , -Invoking m4}), unless overridden by other command line options. - -@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 @acronym{GNU} @code{m4} to take any number of -arguments, and not only nine (@pxref{Arguments}). - -This means that @code{define(`foo', `$11')} is ambiguous between -implementations. To portably choose between grabbing the first -parameter and appending 1 to the expansion, or grabbing the eleventh -parameter, you can do the following: - -@example -define(`a1', `A1') -@result{} -dnl First argument, concatenated with 1 -define(`_1', `$1')define(`first1', `_1($@@)1') -@result{} -dnl Eleventh argument, portable -define(`_9', `$9')define(`eleventh', `_9(shift(shift($@@)))') -@result{} -dnl Eleventh argument, GNU style -define(`Eleventh', `$11') -@result{} -first1(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') -@result{}A1 -eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') -@result{}k -Eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') -@result{}k -@end example - -@item -The @code{divert} (@pxref{Divert}) macro can manage more than 9 -diversions. @acronym{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 -@env{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. - -@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 format of the output from @code{dumpdef} and macro tracing can be -controlled with @code{debugmode} (@pxref{Debug Levels}). - -@item -The destination of trace and debug output can be controlled with -@code{debugfile} (@pxref{Debug Output}). - -@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. -@end itemize - -In addition to the above extensions, @acronym{GNU} @code{m4} implements the -following command line options: @option{-F}, @option{-G}, @option{-I}, -@option{-L}, @option{-R}, @option{-V}, @option{-W}, @option{-d}, @option{-i}, -@option{-l}, @option{--debugfile} and @option{-t}. @xref{Invoking m4}, for a -description of these options. - -Also, the debugging and tracing facilities in @acronym{GNU} @code{m4} are much -more extensive than in most other versions of @code{m4}. - -@node Incompatibilities -@section Facilities in System V @code{m4} not in @acronym{GNU} @code{m4} - -The version of @code{m4} from System V contains a few facilities that -have not been implemented in @acronym{GNU} @code{m4} yet. Additionally, -@acronym{POSIX} requires some behaviors that @acronym{GNU} @code{m4} has not -implemented yet. Relying on these behaviors is non-portable, as a -future release of @acronym{GNU} @code{m4} may change. - -@itemize @bullet -@item -System V @code{m4} supports multiple arguments to @code{defn}, and -@acronym{POSIX} requires it. This is not yet implemented in @acronym{GNU} -@code{m4}. Unfortunately, this means it is not possible to mix builtins -and other text into a single macro; a helper macro is required. - -@item -@acronym{POSIX} requires an application to exit with non-zero status if -it wrote an error message to stderr. This has not yet been consistently -implemented for the various builtins that are required to issue an error -(such as @code{include} (@pxref{Include}) when a file is unreadable, -@code{eval} (@pxref{Eval}) when an argument cannot be parsed, or using -@code{m4exit} (@pxref{M4exit}) with a non-numeric argument). - -@item -Some traditional implementations only allow reading standard input -once, but @acronym{GNU} @code{m4} correctly handles multiple instances -of @samp{-} on the command line. - -@item -@acronym{POSIX} requires @code{m4wrap} (@pxref{M4wrap}) to act in FIFO -(first-in, first-out) order, but @acronym{GNU} @code{m4} currently uses -LIFO order. Furthermore, @acronym{POSIX} states that only the first -argument to @code{m4wrap} is saved for later evaluation, bug -@acronym{GNU} @code{m4} saves and processes all arguments, with output -separated by spaces. - -However, it is possible to emulate @acronym{POSIX} behavior by -including the file @file{m4-@value{VERSION}/@/examples/@/wrapfifo.m4} -from the distribution: - -@example -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 - -@item -@acronym{POSIX} requires that all builtins that require arguments, but -are called without arguments, behave as though empty strings had been -passed. For example, @code{a`'define`'b} would expand to @code{ab}. -But @acronym{GNU} @code{m4} ignores certain builtins if they have missing -arguments, giving @code{adefineb} for the above example. - -@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. @acronym{GNU} @code{m4} replaces just the top -definition on the stack, as if doing @code{popdef(`f')} followed by -@code{pushdef(`f',`1')}. - -@item -@acronym{POSIX} requires @code{syscmd} (@pxref{Syscmd}) to evaluate -command output for macro expansion, but this appears to be a mistake -in @acronym{POSIX} since traditional implementations did not do this. -@acronym{GNU} @code{m4} follows traditional behavior in @code{syscmd}, and -provides the extension @code{esyscmd} that provides the @acronym{POSIX} -semantics. - -@item -At one point, @acronym{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 @acronym{POSIX} is anticipated to state -that using empty strings or just one argument is unspecified. -Meanwhile, the @acronym{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, @acronym{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 @acronym{POSIX} is anticipated to state -that using empty strings is unspecified. Meanwhile, the @acronym{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 @acronym{POSIX}. For -predictable results, never call changecom with empty strings for -arguments. - -@item -Most implementations of @code{m4} give macros a higher precedence than -comments when parsing, meaning that if the start delimiter given to -@code{changecom} (@pxref{Changecom}) starts with a macro name, comments -are effectively disabled. @acronym{POSIX} does not specify what the -precedence is, so the @acronym{GNU} @code{m4} parser recognizes -comments, then macros, then quoted strings. - -@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 @acronym{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 @acronym{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 -Traditional @code{m4} treats @code{traceon} (@pxref{Trace}) without -arguments as a global variable, independent of named macro tracing. -Also, once a macro is undefined, named tracing of that macro is lost. -On the other hand, when @acronym{GNU} @code{m4} encounters -@code{traceon} without -arguments, it turns tracing on for all existing definitions at the time, -but does not trace future definitions; @code{traceoff} without arguments -turns tracing off for all definitions regardless of whether they were -also traced by name; and tracing by name, such as with @option{-tfoo} at -the command line or @code{traceon(`foo')} in the input, is an attribute -that is preserved even if the macro is currently undefined. - -@item -@acronym{POSIX} requires @code{eval} (@pxref{Eval}) to treat all -operators with the same precedence as C. However, @acronym{GNU} @code{m4} -currently follows the traditional precedence of other @code{m4} -implementations, where bitwise and logical negation (@samp{~} and -@samp{!}) have lower precedence than equality operators, rather than -equal precedence with other unary operators. Use explicit parentheses -to ensure proper precedence. As extensions to @acronym{POSIX}, @acronym{GNU} -@code{m4} treats the shift operators @samp{<<} and @samp{>>} as -well-defined on signed integers (even though they are not in C), and -adds the exponentiation operator @samp{**}. - -@item -@acronym{POSIX} requires @code{translit} (@pxref{Translit}) to treat -each character of the second and third arguments literally, but @acronym{GNU} -@code{m4} treats @samp{-} as a range operator. - -@item -@acronym{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 @acronym{GNU} @code{m4}. - -@item -@acronym{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 @acronym{POSIX}, since most -traditional implementations also ignore all whitespace (formfeed, -carriage return, and vertical tab). @acronym{GNU} @code{m4} follows -tradition and ignores all leading unquoted whitespace. -@end itemize - -@node Other Incompatibilities -@section Other incompatibilities - -There are a few other incompatibilities between this implementation of -@code{m4}, and the System V version. - -@itemize @bullet -@item -@acronym{GNU} @code{m4} implements sync lines differently from System V -@code{m4}, when text is being diverted. @acronym{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 @acronym{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 were made, and not where it was inserted again. - -@item -@acronym{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 - -There is nothing inherently wrong with defining @samp{x} to -return @samp{x}. The wrong thing is to expand @samp{x} unquoted. -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 @acronym{GNU} @code{m4} user to hang himself! Rescanning hangs may be -avoided through careful programming, a little like for endless loops -in traditional programming languages. -@end itemize - -@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 cleardivert:: Solution for @code{cleardivert} -* 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}/@/examples/@/forloop2.m4}; this -version also optimizes based on the fact that the starting bound does -not need to be passed to the helper @code{@w{_forloop}}. - -@example -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(`($3) >= ($2)'), `1', -@result{} `pushdef(`$1', eval(`$2'))_forloop(`$1', -@result{} eval(`$3'), `$4')popdef(`$1')')') -@result{}define(`_forloop', -@result{} `$3`'ifelse(indir(`$1'), `$2', `', -@result{} `define(`$1', incr(indir(`$1')))$0($@@)')') -@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: bad expression in eval (bad input): (b) >= (a) -@result{} -@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. @acronym{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}: - -@example -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 - -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}/@/examples/@/foreachq2.m4}: - -@example -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')_foreachq($@@)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. - -For a different approach, the improved version of @code{foreach}, -available in @file{m4-@value{VERSION}/@/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: - -@example -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')_foreach(`$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 - -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 the original -implementations. This points out one other difference between the two -list styles. @code{foreach} evaluates unquoted list elements only once, -in preparation for calling @code{@w{_foreach}}. But @code{foreachq} -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. - -@example -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(`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 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 fatal_error -@section Solution for @code{fatal_error} - -The @code{fatal_error} macro (@pxref{M4exit}) is not robust to versions -of @acronym{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: - -@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: excess arguments to builtin `divnum' ignored -@result{}0 -@error{}m4:stdin:6: fatal error: inside wrapped text -@end example - -@c ========================================================== Appendices - -@node Copying This Manual -@appendix How to make copies of this manual -@cindex License - -@menu -* GNU Free Documentation License:: License for copying this manual -@end menu - -@include fdl.texi - -@node Indices -@appendix Indices of concepts and macros - -@menu -* Concept index:: Index for many concepts -* Macro index:: Index for all @code{m4} macros -@end menu - -@node Concept index -@appendixsec Index for many concepts - -@printindex cp - -@node Macro index -@appendixsec Index for all @code{m4} macros - -References are exclusively to the places where a builtin is introduced -the first time. - -@iftex -@sp 1 -@end iftex - -@printindex fn - -@bye - -@c Local Variables: -@c coding: ISO-8859-1 -@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/src/bin/m4/doc/mdate-sh b/src/bin/m4/doc/mdate-sh deleted file mode 100755 index cd916c0a34..0000000000 --- a/src/bin/m4/doc/mdate-sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/bin/sh -# Get modification time of a file or directory and pretty-print it. - -scriptversion=2005-06-29.22 - -# Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005 Free Software -# Foundation, Inc. -# written by Ulrich Drepper , June 1995 -# -# 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 2, 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, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -case $1 in - '') - echo "$0: No file. Try \`$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: mdate-sh [--help] [--version] FILE - -Pretty-print the modification time of FILE. - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "mdate-sh $scriptversion" - exit $? - ;; -esac - -# Prevent date giving response in another language. -LANG=C -export LANG -LC_ALL=C -export LC_ALL -LC_TIME=C -export LC_TIME - -# GNU ls changes its time format in response to the TIME_STYLE -# variable. Since we cannot assume `unset' works, revert this -# variable to its documented default. -if test "${TIME_STYLE+set}" = set; then - TIME_STYLE=posix-long-iso - export TIME_STYLE -fi - -save_arg1=$1 - -# Find out how to get the extended ls output of a file or directory. -if ls -L /dev/null 1>/dev/null 2>&1; then - ls_command='ls -L -l -d' -else - ls_command='ls -l -d' -fi - -# A `ls -l' line looks as follows on OS/2. -# drwxrwx--- 0 Aug 11 2001 foo -# This differs from Unix, which adds ownership information. -# drwxrwx--- 2 root root 4096 Aug 11 2001 foo -# -# To find the date, we split the line on spaces and iterate on words -# until we find a month. This cannot work with files whose owner is a -# user named `Jan', or `Feb', etc. However, it's unlikely that `/' -# will be owned by a user whose name is a month. So we first look at -# the extended ls output of the root directory to decide how many -# words should be skipped to get the date. - -# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. -set x`ls -l -d /` - -# Find which argument is the month. -month= -command= -until test $month -do - shift - # Add another shift to the command. - command="$command shift;" - case $1 in - Jan) month=January; nummonth=1;; - Feb) month=February; nummonth=2;; - Mar) month=March; nummonth=3;; - Apr) month=April; nummonth=4;; - May) month=May; nummonth=5;; - Jun) month=June; nummonth=6;; - Jul) month=July; nummonth=7;; - Aug) month=August; nummonth=8;; - Sep) month=September; nummonth=9;; - Oct) month=October; nummonth=10;; - Nov) month=November; nummonth=11;; - Dec) month=December; nummonth=12;; - esac -done - -# Get the extended ls output of the file or directory. -set dummy x`eval "$ls_command \"\$save_arg1\""` - -# Remove all preceding arguments -eval $command - -# Because of the dummy argument above, month is in $2. -# -# On a POSIX system, we should have -# -# $# = 5 -# $1 = file size -# $2 = month -# $3 = day -# $4 = year or time -# $5 = filename -# -# On Darwin 7.7.0 and 7.6.0, we have -# -# $# = 4 -# $1 = day -# $2 = month -# $3 = year or time -# $4 = filename - -# Get the month. -case $2 in - Jan) month=January; nummonth=1;; - Feb) month=February; nummonth=2;; - Mar) month=March; nummonth=3;; - Apr) month=April; nummonth=4;; - May) month=May; nummonth=5;; - Jun) month=June; nummonth=6;; - Jul) month=July; nummonth=7;; - Aug) month=August; nummonth=8;; - Sep) month=September; nummonth=9;; - Oct) month=October; nummonth=10;; - Nov) month=November; nummonth=11;; - Dec) month=December; nummonth=12;; -esac - -case $3 in - ???*) day=$1;; - *) day=$3; shift;; -esac - -# Here we have to deal with the problem that the ls output gives either -# the time of day or the year. -case $3 in - *:*) set `date`; eval year=\$$# - case $2 in - Jan) nummonthtod=1;; - Feb) nummonthtod=2;; - Mar) nummonthtod=3;; - Apr) nummonthtod=4;; - May) nummonthtod=5;; - Jun) nummonthtod=6;; - Jul) nummonthtod=7;; - Aug) nummonthtod=8;; - Sep) nummonthtod=9;; - Oct) nummonthtod=10;; - Nov) nummonthtod=11;; - Dec) nummonthtod=12;; - esac - # For the first six month of the year the time notation can also - # be used for files modified in the last year. - if (expr $nummonth \> $nummonthtod) > /dev/null; - then - year=`expr $year - 1` - fi;; - *) year=$3;; -esac - -# The result. -echo $day $month $year - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/src/bin/m4/doc/stamp-vti b/src/bin/m4/doc/stamp-vti deleted file mode 100644 index c9d4e2fb98..0000000000 --- a/src/bin/m4/doc/stamp-vti +++ /dev/null @@ -1,4 +0,0 @@ -@set UPDATED 20 November 2006 -@set UPDATED-MONTH November 2006 -@set EDITION 1.4.8 -@set VERSION 1.4.8 diff --git a/src/bin/m4/doc/texinfo.tex b/src/bin/m4/doc/texinfo.tex deleted file mode 100644 index ab95370db4..0000000000 --- a/src/bin/m4/doc/texinfo.tex +++ /dev/null @@ -1,7483 +0,0 @@ -% texinfo.tex -- TeX macros to handle Texinfo files. -% -% Load plain if necessary, i.e., if running under initex. -\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi -% -\def\texinfoversion{2006-10-15.13} -% -% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, -% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free -% Software Foundation, Inc. -% -% This texinfo.tex 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 2, or (at -% your option) any later version. -% -% This texinfo.tex 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 texinfo.tex file; see the file COPYING. If not, write -% to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -% Boston, MA 02110-1301, USA. -% -% As a special exception, when this file is read by TeX when processing -% a Texinfo source document, you may use the result without -% restriction. (This has been our intent since Texinfo was invented.) -% -% Please try the latest version of texinfo.tex before submitting bug -% reports; you can get the latest version from: -% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or -% ftp://tug.org/tex/texinfo.tex -% (and all CTAN mirrors, see http://www.ctan.org). -% The texinfo.tex in any given distribution could well be out -% of date, so if that's what you're using, please check. -% -% Send bug reports to bug-texinfo@gnu.org. Please include including a -% complete document in each bug report with which we can reproduce the -% problem. Patches are, of course, greatly appreciated. -% -% To process a Texinfo manual with TeX, it's most reliable to use the -% texi2dvi shell script that comes with the distribution. For a simple -% manual foo.texi, however, you can get away with this: -% tex foo.texi -% texindex foo.?? -% tex foo.texi -% tex foo.texi -% dvips foo.dvi -o # or whatever; this makes foo.ps. -% The extra TeX runs get the cross-reference information correct. -% Sometimes one run after texindex suffices, and sometimes you need more -% than two; texi2dvi does it as many times as necessary. -% -% It is possible to adapt texinfo.tex for other languages, to some -% extent. You can get the existing language-specific files from the -% full Texinfo distribution. -% -% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. - - -\message{Loading texinfo [version \texinfoversion]:} - -% If in a .fmt file, print the version number -% and turn on active characters that we couldn't do earlier because -% they might have appeared in the input file name. -\everyjob{\message{[Texinfo version \texinfoversion]}% - \catcode`+=\active \catcode`\_=\active} - -\message{Basics,} -\chardef\other=12 - -% We never want plain's \outer definition of \+ in Texinfo. -% For @tex, we can use \tabalign. -\let\+ = \relax - -% Save some plain tex macros whose names we will redefine. -\let\ptexb=\b -\let\ptexbullet=\bullet -\let\ptexc=\c -\let\ptexcomma=\, -\let\ptexdot=\. -\let\ptexdots=\dots -\let\ptexend=\end -\let\ptexequiv=\equiv -\let\ptexexclam=\! -\let\ptexfootnote=\footnote -\let\ptexgtr=> -\let\ptexhat=^ -\let\ptexi=\i -\let\ptexindent=\indent -\let\ptexinsert=\insert -\let\ptexlbrace=\{ -\let\ptexless=< -\let\ptexnewwrite\newwrite -\let\ptexnoindent=\noindent -\let\ptexplus=+ -\let\ptexrbrace=\} -\let\ptexslash=\/ -\let\ptexstar=\* -\let\ptext=\t - -% If this character appears in an error message or help string, it -% starts a new line in the output. -\newlinechar = `^^J - -% Use TeX 3.0's \inputlineno to get the line number, for better error -% messages, but if we're using an old version of TeX, don't do anything. -% -\ifx\inputlineno\thisisundefined - \let\linenumber = \empty % Pre-3.0. -\else - \def\linenumber{l.\the\inputlineno:\space} -\fi - -% Set up fixed words for English if not already set. -\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi -\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi -\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi -\ifx\putwordin\undefined \gdef\putwordin{in}\fi -\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi -\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi -\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi -\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi -\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi -\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi -\ifx\putwordof\undefined \gdef\putwordof{of}\fi -\ifx\putwordon\undefined \gdef\putwordon{on}\fi -\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi -\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi -\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi -\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi -\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi -\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi -\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi -% -\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi -\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi -\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi -\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi -\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi -\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi -\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi -\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi -\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi -\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi -\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi -\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi -% -\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi -\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi -\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi -\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi -\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi - -% Since the category of space is not known, we have to be careful. -\chardef\spacecat = 10 -\def\spaceisspace{\catcode`\ =\spacecat} - -% sometimes characters are active, so we need control sequences. -\chardef\colonChar = `\: -\chardef\commaChar = `\, -\chardef\dashChar = `\- -\chardef\dotChar = `\. -\chardef\exclamChar= `\! -\chardef\lquoteChar= `\` -\chardef\questChar = `\? -\chardef\rquoteChar= `\' -\chardef\semiChar = `\; -\chardef\underChar = `\_ - -% Ignore a token. -% -\def\gobble#1{} - -% The following is used inside several \edef's. -\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} - -% Hyphenation fixes. -\hyphenation{ - Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script - ap-pen-dix bit-map bit-maps - data-base data-bases eshell fall-ing half-way long-est man-u-script - man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm - par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces - spell-ing spell-ings - stand-alone strong-est time-stamp time-stamps which-ever white-space - wide-spread wrap-around -} - -% Margin to add to right of even pages, to left of odd pages. -\newdimen\bindingoffset -\newdimen\normaloffset -\newdimen\pagewidth \newdimen\pageheight - -% For a final copy, take out the rectangles -% that mark overfull boxes (in case you have decided -% that the text looks ok even though it passes the margin). -% -\def\finalout{\overfullrule=0pt} - -% @| inserts a changebar to the left of the current line. It should -% surround any changed text. This approach does *not* work if the -% change spans more than two lines of output. To handle that, we would -% have adopt a much more difficult approach (putting marks into the main -% vertical list for the beginning and end of each change). -% -\def\|{% - % \vadjust can only be used in horizontal mode. - \leavevmode - % - % Append this vertical mode material after the current line in the output. - \vadjust{% - % We want to insert a rule with the height and depth of the current - % leading; that is exactly what \strutbox is supposed to record. - \vskip-\baselineskip - % - % \vadjust-items are inserted at the left edge of the type. So - % the \llap here moves out into the left-hand margin. - \llap{% - % - % For a thicker or thinner bar, change the `1pt'. - \vrule height\baselineskip width1pt - % - % This is the space between the bar and the text. - \hskip 12pt - }% - }% -} - -% Sometimes it is convenient to have everything in the transcript file -% and nothing on the terminal. We don't just call \tracingall here, -% since that produces some useless output on the terminal. We also make -% some effort to order the tracing commands to reduce output in the log -% file; cf. trace.sty in LaTeX. -% -\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% -\def\loggingall{% - \tracingstats2 - \tracingpages1 - \tracinglostchars2 % 2 gives us more in etex - \tracingparagraphs1 - \tracingoutput1 - \tracingmacros2 - \tracingrestores1 - \showboxbreadth\maxdimen \showboxdepth\maxdimen - \ifx\eTeXversion\undefined\else % etex gives us more logging - \tracingscantokens1 - \tracingifs1 - \tracinggroups1 - \tracingnesting2 - \tracingassigns1 - \fi - \tracingcommands3 % 3 gives us more in etex - \errorcontextlines16 -}% - -% add check for \lastpenalty to plain's definitions. If the last thing -% we did was a \nobreak, we don't want to insert more space. -% -\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount - \removelastskip\penalty-50\smallskip\fi\fi} -\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount - \removelastskip\penalty-100\medskip\fi\fi} -\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount - \removelastskip\penalty-200\bigskip\fi\fi} - -% For @cropmarks command. -% Do @cropmarks to get crop marks. -% -\newif\ifcropmarks -\let\cropmarks = \cropmarkstrue -% -% Dimensions to add cropmarks at corners. -% Added by P. A. MacKay, 12 Nov. 1986 -% -\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines -\newdimen\cornerlong \cornerlong=1pc -\newdimen\cornerthick \cornerthick=.3pt -\newdimen\topandbottommargin \topandbottommargin=.75in - -% Main output routine. -\chardef\PAGE = 255 -\output = {\onepageout{\pagecontents\PAGE}} - -\newbox\headlinebox -\newbox\footlinebox - -% \onepageout takes a vbox as an argument. Note that \pagecontents -% does insertions, but you have to call it yourself. -\def\onepageout#1{% - \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi - % - \ifodd\pageno \advance\hoffset by \bindingoffset - \else \advance\hoffset by -\bindingoffset\fi - % - % Do this outside of the \shipout so @code etc. will be expanded in - % the headline as they should be, not taken literally (outputting ''code). - \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% - \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% - % - {% - % Have to do this stuff outside the \shipout because we want it to - % take effect in \write's, yet the group defined by the \vbox ends - % before the \shipout runs. - % - \indexdummies % don't expand commands in the output. - \normalturnoffactive % \ in index entries must not stay \, e.g., if - % the page break happens to be in the middle of an example. - % We don't want .vr (or whatever) entries like this: - % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} - % "\acronym" won't work when it's read back in; - % it needs to be - % {\code {{\tt \backslashcurfont }acronym} - \shipout\vbox{% - % Do this early so pdf references go to the beginning of the page. - \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi - % - \ifcropmarks \vbox to \outervsize\bgroup - \hsize = \outerhsize - \vskip-\topandbottommargin - \vtop to0pt{% - \line{\ewtop\hfil\ewtop}% - \nointerlineskip - \line{% - \vbox{\moveleft\cornerthick\nstop}% - \hfill - \vbox{\moveright\cornerthick\nstop}% - }% - \vss}% - \vskip\topandbottommargin - \line\bgroup - \hfil % center the page within the outer (page) hsize. - \ifodd\pageno\hskip\bindingoffset\fi - \vbox\bgroup - \fi - % - \unvbox\headlinebox - \pagebody{#1}% - \ifdim\ht\footlinebox > 0pt - % Only leave this space if the footline is nonempty. - % (We lessened \vsize for it in \oddfootingyyy.) - % The \baselineskip=24pt in plain's \makefootline has no effect. - \vskip 24pt - \unvbox\footlinebox - \fi - % - \ifcropmarks - \egroup % end of \vbox\bgroup - \hfil\egroup % end of (centering) \line\bgroup - \vskip\topandbottommargin plus1fill minus1fill - \boxmaxdepth = \cornerthick - \vbox to0pt{\vss - \line{% - \vbox{\moveleft\cornerthick\nsbot}% - \hfill - \vbox{\moveright\cornerthick\nsbot}% - }% - \nointerlineskip - \line{\ewbot\hfil\ewbot}% - }% - \egroup % \vbox from first cropmarks clause - \fi - }% end of \shipout\vbox - }% end of group with \indexdummies - \advancepageno - \ifnum\outputpenalty>-20000 \else\dosupereject\fi -} - -\newinsert\margin \dimen\margin=\maxdimen - -\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} -{\catcode`\@ =11 -\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi -% marginal hacks, juha@viisa.uucp (Juha Takala) -\ifvoid\margin\else % marginal info is present - \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi -\dimen@=\dp#1 \unvbox#1 -\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi -\ifr@ggedbottom \kern-\dimen@ \vfil \fi} -} - -% Here are the rules for the cropmarks. Note that they are -% offset so that the space between them is truly \outerhsize or \outervsize -% (P. A. MacKay, 12 November, 1986) -% -\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} -\def\nstop{\vbox - {\hrule height\cornerthick depth\cornerlong width\cornerthick}} -\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} -\def\nsbot{\vbox - {\hrule height\cornerlong depth\cornerthick width\cornerthick}} - -% Parse an argument, then pass it to #1. The argument is the rest of -% the input line (except we remove a trailing comment). #1 should be a -% macro which expects an ordinary undelimited TeX argument. -% -\def\parsearg{\parseargusing{}} -\def\parseargusing#1#2{% - \def\argtorun{#2}% - \begingroup - \obeylines - \spaceisspace - #1% - \parseargline\empty% Insert the \empty token, see \finishparsearg below. -} - -{\obeylines % - \gdef\parseargline#1^^M{% - \endgroup % End of the group started in \parsearg. - \argremovecomment #1\comment\ArgTerm% - }% -} - -% First remove any @comment, then any @c comment. -\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} -\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} - -% Each occurence of `\^^M' or `\^^M' is replaced by a single space. -% -% \argremovec might leave us with trailing space, e.g., -% @end itemize @c foo -% This space token undergoes the same procedure and is eventually removed -% by \finishparsearg. -% -\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} -\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} -\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% - \def\temp{#3}% - \ifx\temp\empty - % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: - \let\temp\finishparsearg - \else - \let\temp\argcheckspaces - \fi - % Put the space token in: - \temp#1 #3\ArgTerm -} - -% If a _delimited_ argument is enclosed in braces, they get stripped; so -% to get _exactly_ the rest of the line, we had to prevent such situation. -% We prepended an \empty token at the very beginning and we expand it now, -% just before passing the control to \argtorun. -% (Similarily, we have to think about #3 of \argcheckspacesY above: it is -% either the null string, or it ends with \^^M---thus there is no danger -% that a pair of braces would be stripped. -% -% But first, we have to remove the trailing space token. -% -\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} - -% \parseargdef\foo{...} -% is roughly equivalent to -% \def\foo{\parsearg\Xfoo} -% \def\Xfoo#1{...} -% -% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my -% favourite TeX trick. --kasal, 16nov03 - -\def\parseargdef#1{% - \expandafter \doparseargdef \csname\string#1\endcsname #1% -} -\def\doparseargdef#1#2{% - \def#2{\parsearg#1}% - \def#1##1% -} - -% Several utility definitions with active space: -{ - \obeyspaces - \gdef\obeyedspace{ } - - % Make each space character in the input produce a normal interword - % space in the output. Don't allow a line break at this space, as this - % is used only in environments like @example, where each line of input - % should produce a line of output anyway. - % - \gdef\sepspaces{\obeyspaces\let =\tie} - - % If an index command is used in an @example environment, any spaces - % therein should become regular spaces in the raw index file, not the - % expansion of \tie (\leavevmode \penalty \@M \ ). - \gdef\unsepspaces{\let =\space} -} - - -\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} - -% Define the framework for environments in texinfo.tex. It's used like this: -% -% \envdef\foo{...} -% \def\Efoo{...} -% -% It's the responsibility of \envdef to insert \begingroup before the -% actual body; @end closes the group after calling \Efoo. \envdef also -% defines \thisenv, so the current environment is known; @end checks -% whether the environment name matches. The \checkenv macro can also be -% used to check whether the current environment is the one expected. -% -% Non-false conditionals (@iftex, @ifset) don't fit into this, so they -% are not treated as enviroments; they don't open a group. (The -% implementation of @end takes care not to call \endgroup in this -% special case.) - - -% At runtime, environments start with this: -\def\startenvironment#1{\begingroup\def\thisenv{#1}} -% initialize -\let\thisenv\empty - -% ... but they get defined via ``\envdef\foo{...}'': -\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} -\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} - -% Check whether we're in the right environment: -\def\checkenv#1{% - \def\temp{#1}% - \ifx\thisenv\temp - \else - \badenverr - \fi -} - -% Evironment mismatch, #1 expected: -\def\badenverr{% - \errhelp = \EMsimple - \errmessage{This command can appear only \inenvironment\temp, - not \inenvironment\thisenv}% -} -\def\inenvironment#1{% - \ifx#1\empty - out of any environment% - \else - in environment \expandafter\string#1% - \fi -} - -% @end foo executes the definition of \Efoo. -% But first, it executes a specialized version of \checkenv -% -\parseargdef\end{% - \if 1\csname iscond.#1\endcsname - \else - % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 - \expandafter\checkenv\csname#1\endcsname - \csname E#1\endcsname - \endgroup - \fi -} - -\newhelp\EMsimple{Press RETURN to continue.} - - -%% Simple single-character @ commands - -% @@ prints an @ -% Kludge this until the fonts are right (grr). -\def\@{{\tt\char64}} - -% This is turned off because it was never documented -% and you can use @w{...} around a quote to suppress ligatures. -%% Define @` and @' to be the same as ` and ' -%% but suppressing ligatures. -%\def\`{{`}} -%\def\'{{'}} - -% Used to generate quoted braces. -\def\mylbrace {{\tt\char123}} -\def\myrbrace {{\tt\char125}} -\let\{=\mylbrace -\let\}=\myrbrace -\begingroup - % Definitions to produce \{ and \} commands for indices, - % and @{ and @} for the aux/toc files. - \catcode`\{ = \other \catcode`\} = \other - \catcode`\[ = 1 \catcode`\] = 2 - \catcode`\! = 0 \catcode`\\ = \other - !gdef!lbracecmd[\{]% - !gdef!rbracecmd[\}]% - !gdef!lbraceatcmd[@{]% - !gdef!rbraceatcmd[@}]% -!endgroup - -% @comma{} to avoid , parsing problems. -\let\comma = , - -% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent -% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. -\let\, = \c -\let\dotaccent = \. -\def\ringaccent#1{{\accent23 #1}} -\let\tieaccent = \t -\let\ubaraccent = \b -\let\udotaccent = \d - -% Other special characters: @questiondown @exclamdown @ordf @ordm -% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. -\def\questiondown{?`} -\def\exclamdown{!`} -\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} -\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} - -% Dotless i and dotless j, used for accents. -\def\imacro{i} -\def\jmacro{j} -\def\dotless#1{% - \def\temp{#1}% - \ifx\temp\imacro \ptexi - \else\ifx\temp\jmacro \j - \else \errmessage{@dotless can be used only with i or j}% - \fi\fi -} - -% The \TeX{} logo, as in plain, but resetting the spacing so that a -% period following counts as ending a sentence. (Idea found in latex.) -% -\edef\TeX{\TeX \spacefactor=1000 } - -% @LaTeX{} logo. Not quite the same results as the definition in -% latex.ltx, since we use a different font for the raised A; it's most -% convenient for us to use an explicitly smaller font, rather than using -% the \scriptstyle font (since we don't reset \scriptstyle and -% \scriptscriptstyle). -% -\def\LaTeX{% - L\kern-.36em - {\setbox0=\hbox{T}% - \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% - \kern-.15em - \TeX -} - -% Be sure we're in horizontal mode when doing a tie, since we make space -% equivalent to this in @example-like environments. Otherwise, a space -% at the beginning of a line will start with \penalty -- and -% since \penalty is valid in vertical mode, we'd end up putting the -% penalty on the vertical list instead of in the new paragraph. -{\catcode`@ = 11 - % Avoid using \@M directly, because that causes trouble - % if the definition is written into an index file. - \global\let\tiepenalty = \@M - \gdef\tie{\leavevmode\penalty\tiepenalty\ } -} - -% @: forces normal size whitespace following. -\def\:{\spacefactor=1000 } - -% @* forces a line break. -\def\*{\hfil\break\hbox{}\ignorespaces} - -% @/ allows a line break. -\let\/=\allowbreak - -% @. is an end-of-sentence period. -\def\.{.\spacefactor=\endofsentencespacefactor\space} - -% @! is an end-of-sentence bang. -\def\!{!\spacefactor=\endofsentencespacefactor\space} - -% @? is an end-of-sentence query. -\def\?{?\spacefactor=\endofsentencespacefactor\space} - -% @frenchspacing on|off says whether to put extra space after punctuation. -% -\def\onword{on} -\def\offword{off} -% -\parseargdef\frenchspacing{% - \def\temp{#1}% - \ifx\temp\onword \plainfrenchspacing - \else\ifx\temp\offword \plainnonfrenchspacing - \else - \errhelp = \EMsimple - \errmessage{Unknown @frenchspacing option `\temp', must be on/off}% - \fi\fi -} - -% @w prevents a word break. Without the \leavevmode, @w at the -% beginning of a paragraph, when TeX is still in vertical mode, would -% produce a whole line of output instead of starting the paragraph. -\def\w#1{\leavevmode\hbox{#1}} - -% @group ... @end group forces ... to be all on one page, by enclosing -% it in a TeX vbox. We use \vtop instead of \vbox to construct the box -% to keep its height that of a normal line. According to the rules for -% \topskip (p.114 of the TeXbook), the glue inserted is -% max (\topskip - \ht (first item), 0). If that height is large, -% therefore, no glue is inserted, and the space between the headline and -% the text is small, which looks bad. -% -% Another complication is that the group might be very large. This can -% cause the glue on the previous page to be unduly stretched, because it -% does not have much material. In this case, it's better to add an -% explicit \vfill so that the extra space is at the bottom. The -% threshold for doing this is if the group is more than \vfilllimit -% percent of a page (\vfilllimit can be changed inside of @tex). -% -\newbox\groupbox -\def\vfilllimit{0.7} -% -\envdef\group{% - \ifnum\catcode`\^^M=\active \else - \errhelp = \groupinvalidhelp - \errmessage{@group invalid in context where filling is enabled}% - \fi - \startsavinginserts - % - \setbox\groupbox = \vtop\bgroup - % Do @comment since we are called inside an environment such as - % @example, where each end-of-line in the input causes an - % end-of-line in the output. We don't want the end-of-line after - % the `@group' to put extra space in the output. Since @group - % should appear on a line by itself (according to the Texinfo - % manual), we don't worry about eating any user text. - \comment -} -% -% The \vtop produces a box with normal height and large depth; thus, TeX puts -% \baselineskip glue before it, and (when the next line of text is done) -% \lineskip glue after it. Thus, space below is not quite equal to space -% above. But it's pretty close. -\def\Egroup{% - % To get correct interline space between the last line of the group - % and the first line afterwards, we have to propagate \prevdepth. - \endgraf % Not \par, as it may have been set to \lisppar. - \global\dimen1 = \prevdepth - \egroup % End the \vtop. - % \dimen0 is the vertical size of the group's box. - \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox - % \dimen2 is how much space is left on the page (more or less). - \dimen2 = \pageheight \advance\dimen2 by -\pagetotal - % if the group doesn't fit on the current page, and it's a big big - % group, force a page break. - \ifdim \dimen0 > \dimen2 - \ifdim \pagetotal < \vfilllimit\pageheight - \page - \fi - \fi - \box\groupbox - \prevdepth = \dimen1 - \checkinserts -} -% -% TeX puts in an \escapechar (i.e., `@') at the beginning of the help -% message, so this ends up printing `@group can only ...'. -% -\newhelp\groupinvalidhelp{% -group can only be used in environments such as @example,^^J% -where each line of input produces a line of output.} - -% @need space-in-mils -% forces a page break if there is not space-in-mils remaining. - -\newdimen\mil \mil=0.001in - -% Old definition--didn't work. -%\parseargdef\need{\par % -%% This method tries to make TeX break the page naturally -%% if the depth of the box does not fit. -%{\baselineskip=0pt% -%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak -%\prevdepth=-1000pt -%}} - -\parseargdef\need{% - % Ensure vertical mode, so we don't make a big box in the middle of a - % paragraph. - \par - % - % If the @need value is less than one line space, it's useless. - \dimen0 = #1\mil - \dimen2 = \ht\strutbox - \advance\dimen2 by \dp\strutbox - \ifdim\dimen0 > \dimen2 - % - % Do a \strut just to make the height of this box be normal, so the - % normal leading is inserted relative to the preceding line. - % And a page break here is fine. - \vtop to #1\mil{\strut\vfil}% - % - % TeX does not even consider page breaks if a penalty added to the - % main vertical list is 10000 or more. But in order to see if the - % empty box we just added fits on the page, we must make it consider - % page breaks. On the other hand, we don't want to actually break the - % page after the empty box. So we use a penalty of 9999. - % - % There is an extremely small chance that TeX will actually break the - % page at this \penalty, if there are no other feasible breakpoints in - % sight. (If the user is using lots of big @group commands, which - % almost-but-not-quite fill up a page, TeX will have a hard time doing - % good page breaking, for example.) However, I could not construct an - % example where a page broke at this \penalty; if it happens in a real - % document, then we can reconsider our strategy. - \penalty9999 - % - % Back up by the size of the box, whether we did a page break or not. - \kern -#1\mil - % - % Do not allow a page break right after this kern. - \nobreak - \fi -} - -% @br forces paragraph break (and is undocumented). - -\let\br = \par - -% @page forces the start of a new page. -% -\def\page{\par\vfill\supereject} - -% @exdent text.... -% outputs text on separate line in roman font, starting at standard page margin - -% This records the amount of indent in the innermost environment. -% That's how much \exdent should take out. -\newskip\exdentamount - -% This defn is used inside fill environments such as @defun. -\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} - -% This defn is used inside nofill environments such as @example. -\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount - \leftline{\hskip\leftskip{\rm#1}}}} - -% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current -% paragraph. For more general purposes, use the \margin insertion -% class. WHICH is `l' or `r'. -% -\newskip\inmarginspacing \inmarginspacing=1cm -\def\strutdepth{\dp\strutbox} -% -\def\doinmargin#1#2{\strut\vadjust{% - \nobreak - \kern-\strutdepth - \vtop to \strutdepth{% - \baselineskip=\strutdepth - \vss - % if you have multiple lines of stuff to put here, you'll need to - % make the vbox yourself of the appropriate size. - \ifx#1l% - \llap{\ignorespaces #2\hskip\inmarginspacing}% - \else - \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% - \fi - \null - }% -}} -\def\inleftmargin{\doinmargin l} -\def\inrightmargin{\doinmargin r} -% -% @inmargin{TEXT [, RIGHT-TEXT]} -% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; -% else use TEXT for both). -% -\def\inmargin#1{\parseinmargin #1,,\finish} -\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \def\lefttext{#1}% have both texts - \def\righttext{#2}% - \else - \def\lefttext{#1}% have only one text - \def\righttext{#1}% - \fi - % - \ifodd\pageno - \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin - \else - \def\temp{\inleftmargin\lefttext}% - \fi - \temp -} - -% @include file insert text of that file as input. -% -\def\include{\parseargusing\filenamecatcodes\includezzz} -\def\includezzz#1{% - \pushthisfilestack - \def\thisfile{#1}% - {% - \makevalueexpandable - \def\temp{\input #1 }% - \expandafter - }\temp - \popthisfilestack -} -\def\filenamecatcodes{% - \catcode`\\=\other - \catcode`~=\other - \catcode`^=\other - \catcode`_=\other - \catcode`|=\other - \catcode`<=\other - \catcode`>=\other - \catcode`+=\other - \catcode`-=\other -} - -\def\pushthisfilestack{% - \expandafter\pushthisfilestackX\popthisfilestack\StackTerm -} -\def\pushthisfilestackX{% - \expandafter\pushthisfilestackY\thisfile\StackTerm -} -\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% - \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% -} - -\def\popthisfilestack{\errthisfilestackempty} -\def\errthisfilestackempty{\errmessage{Internal error: - the stack of filenames is empty.}} - -\def\thisfile{} - -% @center line -% outputs that line, centered. -% -\parseargdef\center{% - \ifhmode - \let\next\centerH - \else - \let\next\centerV - \fi - \next{\hfil \ignorespaces#1\unskip \hfil}% -} -\def\centerH#1{% - {% - \hfil\break - \advance\hsize by -\leftskip - \advance\hsize by -\rightskip - \line{#1}% - \break - }% -} -\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} - -% @sp n outputs n lines of vertical space - -\parseargdef\sp{\vskip #1\baselineskip} - -% @comment ...line which is ignored... -% @c is the same as @comment -% @ignore ... @end ignore is another way to write a comment - -\def\comment{\begingroup \catcode`\^^M=\other% -\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% -\commentxxx} -{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} - -\let\c=\comment - -% @paragraphindent NCHARS -% We'll use ems for NCHARS, close enough. -% NCHARS can also be the word `asis' or `none'. -% We cannot feasibly implement @paragraphindent asis, though. -% -\def\asisword{asis} % no translation, these are keywords -\def\noneword{none} -% -\parseargdef\paragraphindent{% - \def\temp{#1}% - \ifx\temp\asisword - \else - \ifx\temp\noneword - \defaultparindent = 0pt - \else - \defaultparindent = #1em - \fi - \fi - \parindent = \defaultparindent -} - -% @exampleindent NCHARS -% We'll use ems for NCHARS like @paragraphindent. -% It seems @exampleindent asis isn't necessary, but -% I preserve it to make it similar to @paragraphindent. -\parseargdef\exampleindent{% - \def\temp{#1}% - \ifx\temp\asisword - \else - \ifx\temp\noneword - \lispnarrowing = 0pt - \else - \lispnarrowing = #1em - \fi - \fi -} - -% @firstparagraphindent WORD -% If WORD is `none', then suppress indentation of the first paragraph -% after a section heading. If WORD is `insert', then do indent at such -% paragraphs. -% -% The paragraph indentation is suppressed or not by calling -% \suppressfirstparagraphindent, which the sectioning commands do. -% We switch the definition of this back and forth according to WORD. -% By default, we suppress indentation. -% -\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} -\def\insertword{insert} -% -\parseargdef\firstparagraphindent{% - \def\temp{#1}% - \ifx\temp\noneword - \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent - \else\ifx\temp\insertword - \let\suppressfirstparagraphindent = \relax - \else - \errhelp = \EMsimple - \errmessage{Unknown @firstparagraphindent option `\temp'}% - \fi\fi -} - -% Here is how we actually suppress indentation. Redefine \everypar to -% \kern backwards by \parindent, and then reset itself to empty. -% -% We also make \indent itself not actually do anything until the next -% paragraph. -% -\gdef\dosuppressfirstparagraphindent{% - \gdef\indent{% - \restorefirstparagraphindent - \indent - }% - \gdef\noindent{% - \restorefirstparagraphindent - \noindent - }% - \global\everypar = {% - \kern -\parindent - \restorefirstparagraphindent - }% -} - -\gdef\restorefirstparagraphindent{% - \global \let \indent = \ptexindent - \global \let \noindent = \ptexnoindent - \global \everypar = {}% -} - - -% @asis just yields its argument. Used with @table, for example. -% -\def\asis#1{#1} - -% @math outputs its argument in math mode. -% -% One complication: _ usually means subscripts, but it could also mean -% an actual _ character, as in @math{@var{some_variable} + 1}. So make -% _ active, and distinguish by seeing if the current family is \slfam, -% which is what @var uses. -{ - \catcode`\_ = \active - \gdef\mathunderscore{% - \catcode`\_=\active - \def_{\ifnum\fam=\slfam \_\else\sb\fi}% - } -} -% Another complication: we want \\ (and @\) to output a \ character. -% FYI, plain.tex uses \\ as a temporary control sequence (why?), but -% this is not advertised and we don't care. Texinfo does not -% otherwise define @\. -% -% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. -\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} -% -\def\math{% - \tex - \mathunderscore - \let\\ = \mathbackslash - \mathactive - $\finishmath -} -\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. - -% Some active characters (such as <) are spaced differently in math. -% We have to reset their definitions in case the @math was an argument -% to a command which sets the catcodes (such as @item or @section). -% -{ - \catcode`^ = \active - \catcode`< = \active - \catcode`> = \active - \catcode`+ = \active - \gdef\mathactive{% - \let^ = \ptexhat - \let< = \ptexless - \let> = \ptexgtr - \let+ = \ptexplus - } -} - -% @bullet and @minus need the same treatment as @math, just above. -\def\bullet{$\ptexbullet$} -\def\minus{$-$} - -% @dots{} outputs an ellipsis using the current font. -% We do .5em per period so that it has the same spacing in the cm -% typewriter fonts as three actual period characters; on the other hand, -% in other typewriter fonts three periods are wider than 1.5em. So do -% whichever is larger. -% -\def\dots{% - \leavevmode - \setbox0=\hbox{...}% get width of three periods - \ifdim\wd0 > 1.5em - \dimen0 = \wd0 - \else - \dimen0 = 1.5em - \fi - \hbox to \dimen0{% - \hskip 0pt plus.25fil - .\hskip 0pt plus1fil - .\hskip 0pt plus1fil - .\hskip 0pt plus.5fil - }% -} - -% @enddots{} is an end-of-sentence ellipsis. -% -\def\enddots{% - \dots - \spacefactor=\endofsentencespacefactor -} - -% @comma{} is so commas can be inserted into text without messing up -% Texinfo's parsing. -% -\let\comma = , - -% @refill is a no-op. -\let\refill=\relax - -% If working on a large document in chapters, it is convenient to -% be able to disable indexing, cross-referencing, and contents, for test runs. -% This is done with @novalidate (before @setfilename). -% -\newif\iflinks \linkstrue % by default we want the aux files. -\let\novalidate = \linksfalse - -% @setfilename is done at the beginning of every texinfo file. -% So open here the files we need to have open while reading the input. -% This makes it possible to make a .fmt file for texinfo. -\def\setfilename{% - \fixbackslash % Turn off hack to swallow `\input texinfo'. - \iflinks - \tryauxfile - % Open the new aux file. TeX will close it automatically at exit. - \immediate\openout\auxfile=\jobname.aux - \fi % \openindices needs to do some work in any case. - \openindices - \let\setfilename=\comment % Ignore extra @setfilename cmds. - % - % If texinfo.cnf is present on the system, read it. - % Useful for site-wide @afourpaper, etc. - \openin 1 texinfo.cnf - \ifeof 1 \else \input texinfo.cnf \fi - \closein 1 - % - \comment % Ignore the actual filename. -} - -% Called from \setfilename. -% -\def\openindices{% - \newindex{cp}% - \newcodeindex{fn}% - \newcodeindex{vr}% - \newcodeindex{tp}% - \newcodeindex{ky}% - \newcodeindex{pg}% -} - -% @bye. -\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} - - -\message{pdf,} -% adobe `portable' document format -\newcount\tempnum -\newcount\lnkcount -\newtoks\filename -\newcount\filenamelength -\newcount\pgn -\newtoks\toksA -\newtoks\toksB -\newtoks\toksC -\newtoks\toksD -\newbox\boxA -\newcount\countA -\newif\ifpdf -\newif\ifpdfmakepagedest - -% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 -% can be set). So we test for \relax and 0 as well as \undefined, -% borrowed from ifpdf.sty. -\ifx\pdfoutput\undefined -\else - \ifx\pdfoutput\relax - \else - \ifcase\pdfoutput - \else - \pdftrue - \fi - \fi -\fi - -% PDF uses PostScript string constants for the names of xref targets, -% for display in the outlines, and in other places. Thus, we have to -% double any backslashes. Otherwise, a name like "\node" will be -% interpreted as a newline (\n), followed by o, d, e. Not good. -% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html -% (and related messages, the final outcome is that it is up to the TeX -% user to double the backslashes and otherwise make the string valid, so -% that's what we do). - -% double active backslashes. -% -{\catcode`\@=0 \catcode`\\=\active - @gdef@activebackslashdouble{% - @catcode`@\=@active - @let\=@doublebackslash} -} - -% To handle parens, we must adopt a different approach, since parens are -% not active characters. hyperref.dtx (which has the same problem as -% us) handles it with this amazing macro to replace tokens. I've -% tinkered with it a little for texinfo, but it's definitely from there. -% -% #1 is the tokens to replace. -% #2 is the replacement. -% #3 is the control sequence with the string. -% -\def\HyPsdSubst#1#2#3{% - \def\HyPsdReplace##1#1##2\END{% - ##1% - \ifx\\##2\\% - \else - #2% - \HyReturnAfterFi{% - \HyPsdReplace##2\END - }% - \fi - }% - \xdef#3{\expandafter\HyPsdReplace#3#1\END}% -} -\long\def\HyReturnAfterFi#1\fi{\fi#1} - -% #1 is a control sequence in which to do the replacements. -\def\backslashparens#1{% - \xdef#1{#1}% redefine it as its expansion; the definition is simply - % \lastnode when called from \setref -> \pdfmkdest. - \HyPsdSubst{(}{\realbackslash(}{#1}% - \HyPsdSubst{)}{\realbackslash)}{#1}% -} - -\ifpdf - \input pdfcolor - \pdfcatalog{/PageMode /UseOutlines}% - % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). - \def\dopdfimage#1#2#3{% - \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% - \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% - % without \immediate, pdftex seg faults when the same image is - % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) - \ifnum\pdftexversion < 14 - \immediate\pdfimage - \else - \immediate\pdfximage - \fi - \ifdim \wd0 >0pt width \imagewidth \fi - \ifdim \wd2 >0pt height \imageheight \fi - \ifnum\pdftexversion<13 - #1.pdf% - \else - {#1.pdf}% - \fi - \ifnum\pdftexversion < 14 \else - \pdfrefximage \pdflastximage - \fi} - \def\pdfmkdest#1{{% - % We have to set dummies so commands such as @code, and characters - % such as \, aren't expanded when present in a section title. - \atdummies - \activebackslashdouble - \def\pdfdestname{#1}% - \backslashparens\pdfdestname - \pdfdest name{\pdfdestname} xyz% - }}% - % - % used to mark target names; must be expandable. - \def\pdfmkpgn#1{#1}% - % - \let\linkcolor = \Blue % was Cyan, but that seems light? - \def\endlink{\Black\pdfendlink} - % Adding outlines to PDF; macros for calculating structure of outlines - % come from Petr Olsak - \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% - \else \csname#1\endcsname \fi} - \def\advancenumber#1{\tempnum=\expnumber{#1}\relax - \advance\tempnum by 1 - \expandafter\xdef\csname#1\endcsname{\the\tempnum}} - % - % #1 is the section text, which is what will be displayed in the - % outline by the pdf viewer. #2 is the pdf expression for the number - % of subentries (or empty, for subsubsections). #3 is the node text, - % which might be empty if this toc entry had no corresponding node. - % #4 is the page number - % - \def\dopdfoutline#1#2#3#4{% - % Generate a link to the node text if that exists; else, use the - % page number. We could generate a destination for the section - % text in the case where a section has no node, but it doesn't - % seem worth the trouble, since most documents are normally structured. - \def\pdfoutlinedest{#3}% - \ifx\pdfoutlinedest\empty - \def\pdfoutlinedest{#4}% - \else - % Doubled backslashes in the name. - {\activebackslashdouble \xdef\pdfoutlinedest{#3}% - \backslashparens\pdfoutlinedest}% - \fi - % - % Also double the backslashes in the display string. - {\activebackslashdouble \xdef\pdfoutlinetext{#1}% - \backslashparens\pdfoutlinetext}% - % - \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% - } - % - \def\pdfmakeoutlines{% - \begingroup - % Thanh's hack / proper braces in bookmarks - \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace - \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace - % - % Read toc silently, to get counts of subentries for \pdfoutline. - \def\numchapentry##1##2##3##4{% - \def\thischapnum{##2}% - \def\thissecnum{0}% - \def\thissubsecnum{0}% - }% - \def\numsecentry##1##2##3##4{% - \advancenumber{chap\thischapnum}% - \def\thissecnum{##2}% - \def\thissubsecnum{0}% - }% - \def\numsubsecentry##1##2##3##4{% - \advancenumber{sec\thissecnum}% - \def\thissubsecnum{##2}% - }% - \def\numsubsubsecentry##1##2##3##4{% - \advancenumber{subsec\thissubsecnum}% - }% - \def\thischapnum{0}% - \def\thissecnum{0}% - \def\thissubsecnum{0}% - % - % use \def rather than \let here because we redefine \chapentry et - % al. a second time, below. - \def\appentry{\numchapentry}% - \def\appsecentry{\numsecentry}% - \def\appsubsecentry{\numsubsecentry}% - \def\appsubsubsecentry{\numsubsubsecentry}% - \def\unnchapentry{\numchapentry}% - \def\unnsecentry{\numsecentry}% - \def\unnsubsecentry{\numsubsecentry}% - \def\unnsubsubsecentry{\numsubsubsecentry}% - \readdatafile{toc}% - % - % Read toc second time, this time actually producing the outlines. - % The `-' means take the \expnumber as the absolute number of - % subentries, which we calculated on our first read of the .toc above. - % - % We use the node names as the destinations. - \def\numchapentry##1##2##3##4{% - \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% - \def\numsecentry##1##2##3##4{% - \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% - \def\numsubsecentry##1##2##3##4{% - \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% - \def\numsubsubsecentry##1##2##3##4{% count is always zero - \dopdfoutline{##1}{}{##3}{##4}}% - % - % PDF outlines are displayed using system fonts, instead of - % document fonts. Therefore we cannot use special characters, - % since the encoding is unknown. For example, the eogonek from - % Latin 2 (0xea) gets translated to a | character. Info from - % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. - % - % xx to do this right, we have to translate 8-bit characters to - % their "best" equivalent, based on the @documentencoding. Right - % now, I guess we'll just let the pdf reader have its way. - \indexnofonts - \setupdatafile - \catcode`\\=\active \otherbackslash - \input \jobname.toc - \endgroup - } - % - \def\skipspaces#1{\def\PP{#1}\def\D{|}% - \ifx\PP\D\let\nextsp\relax - \else\let\nextsp\skipspaces - \ifx\p\space\else\addtokens{\filename}{\PP}% - \advance\filenamelength by 1 - \fi - \fi - \nextsp} - \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} - \ifnum\pdftexversion < 14 - \let \startlink \pdfannotlink - \else - \let \startlink \pdfstartlink - \fi - % make a live url in pdf output. - \def\pdfurl#1{% - \begingroup - % it seems we really need yet another set of dummies; have not - % tried to figure out what each command should do in the context - % of @url. for now, just make @/ a no-op, that's the only one - % people have actually reported a problem with. - % - \normalturnoffactive - \def\@{@}% - \let\/=\empty - \makevalueexpandable - \leavevmode\Red - \startlink attr{/Border [0 0 0]}% - user{/Subtype /Link /A << /S /URI /URI (#1) >>}% - \endgroup} - \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} - \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} - \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} - \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} - \def\maketoks{% - \expandafter\poptoks\the\toksA|ENDTOKS|\relax - \ifx\first0\adn0 - \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 - \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 - \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 - \else - \ifnum0=\countA\else\makelink\fi - \ifx\first.\let\next=\done\else - \let\next=\maketoks - \addtokens{\toksB}{\the\toksD} - \ifx\first,\addtokens{\toksB}{\space}\fi - \fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \next} - \def\makelink{\addtokens{\toksB}% - {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} - \def\pdflink#1{% - \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} - \linkcolor #1\endlink} - \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} -\else - \let\pdfmkdest = \gobble - \let\pdfurl = \gobble - \let\endlink = \relax - \let\linkcolor = \relax - \let\pdfmakeoutlines = \relax -\fi % \ifx\pdfoutput - - -\message{fonts,} - -% Change the current font style to #1, remembering it in \curfontstyle. -% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in -% italics, not bold italics. -% -\def\setfontstyle#1{% - \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. - \csname ten#1\endcsname % change the current font -} - -% Select #1 fonts with the current style. -% -\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} - -\def\rm{\fam=0 \setfontstyle{rm}} -\def\it{\fam=\itfam \setfontstyle{it}} -\def\sl{\fam=\slfam \setfontstyle{sl}} -\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} -\def\tt{\fam=\ttfam \setfontstyle{tt}} - -% Texinfo sort of supports the sans serif font style, which plain TeX does not. -% So we set up a \sf. -\newfam\sffam -\def\sf{\fam=\sffam \setfontstyle{sf}} -\let\li = \sf % Sometimes we call it \li, not \sf. - -% We don't need math for this font style. -\def\ttsl{\setfontstyle{ttsl}} - - -% Default leading. -\newdimen\textleading \textleading = 13.2pt - -% Set the baselineskip to #1, and the lineskip and strut size -% correspondingly. There is no deep meaning behind these magic numbers -% used as factors; they just match (closely enough) what Knuth defined. -% -\def\lineskipfactor{.08333} -\def\strutheightpercent{.70833} -\def\strutdepthpercent {.29167} -% -\def\setleading#1{% - \normalbaselineskip = #1\relax - \normallineskip = \lineskipfactor\normalbaselineskip - \normalbaselines - \setbox\strutbox =\hbox{% - \vrule width0pt height\strutheightpercent\baselineskip - depth \strutdepthpercent \baselineskip - }% -} - - -% Set the font macro #1 to the font named #2, adding on the -% specified font prefix (normally `cm'). -% #3 is the font's design size, #4 is a scale factor -\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} - - -% Use cm as the default font prefix. -% To specify the font prefix, you must define \fontprefix -% before you read in texinfo.tex. -\ifx\fontprefix\undefined -\def\fontprefix{cm} -\fi -% Support font families that don't use the same naming scheme as CM. -\def\rmshape{r} -\def\rmbshape{bx} %where the normal face is bold -\def\bfshape{b} -\def\bxshape{bx} -\def\ttshape{tt} -\def\ttbshape{tt} -\def\ttslshape{sltt} -\def\itshape{ti} -\def\itbshape{bxti} -\def\slshape{sl} -\def\slbshape{bxsl} -\def\sfshape{ss} -\def\sfbshape{ss} -\def\scshape{csc} -\def\scbshape{csc} - -% Definitions for a main text size of 11pt. This is the default in -% Texinfo. -% -\def\definetextfontsizexi{ -% Text fonts (11.2pt, magstep1). -\def\textnominalsize{11pt} -\edef\mainmagstep{\magstephalf} -\setfont\textrm\rmshape{10}{\mainmagstep} -\setfont\texttt\ttshape{10}{\mainmagstep} -\setfont\textbf\bfshape{10}{\mainmagstep} -\setfont\textit\itshape{10}{\mainmagstep} -\setfont\textsl\slshape{10}{\mainmagstep} -\setfont\textsf\sfshape{10}{\mainmagstep} -\setfont\textsc\scshape{10}{\mainmagstep} -\setfont\textttsl\ttslshape{10}{\mainmagstep} -\font\texti=cmmi10 scaled \mainmagstep -\font\textsy=cmsy10 scaled \mainmagstep - -% A few fonts for @defun names and args. -\setfont\defbf\bfshape{10}{\magstep1} -\setfont\deftt\ttshape{10}{\magstep1} -\setfont\defttsl\ttslshape{10}{\magstep1} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} - -% Fonts for indices, footnotes, small examples (9pt). -\def\smallnominalsize{9pt} -\setfont\smallrm\rmshape{9}{1000} -\setfont\smalltt\ttshape{9}{1000} -\setfont\smallbf\bfshape{10}{900} -\setfont\smallit\itshape{9}{1000} -\setfont\smallsl\slshape{9}{1000} -\setfont\smallsf\sfshape{9}{1000} -\setfont\smallsc\scshape{10}{900} -\setfont\smallttsl\ttslshape{10}{900} -\font\smalli=cmmi9 -\font\smallsy=cmsy9 - -% Fonts for small examples (8pt). -\def\smallernominalsize{8pt} -\setfont\smallerrm\rmshape{8}{1000} -\setfont\smallertt\ttshape{8}{1000} -\setfont\smallerbf\bfshape{10}{800} -\setfont\smallerit\itshape{8}{1000} -\setfont\smallersl\slshape{8}{1000} -\setfont\smallersf\sfshape{8}{1000} -\setfont\smallersc\scshape{10}{800} -\setfont\smallerttsl\ttslshape{10}{800} -\font\smalleri=cmmi8 -\font\smallersy=cmsy8 - -% Fonts for title page (20.4pt): -\def\titlenominalsize{20pt} -\setfont\titlerm\rmbshape{12}{\magstep3} -\setfont\titleit\itbshape{10}{\magstep4} -\setfont\titlesl\slbshape{10}{\magstep4} -\setfont\titlett\ttbshape{12}{\magstep3} -\setfont\titlettsl\ttslshape{10}{\magstep4} -\setfont\titlesf\sfbshape{17}{\magstep1} -\let\titlebf=\titlerm -\setfont\titlesc\scbshape{10}{\magstep4} -\font\titlei=cmmi12 scaled \magstep3 -\font\titlesy=cmsy10 scaled \magstep4 -\def\authorrm{\secrm} -\def\authortt{\sectt} - -% Chapter (and unnumbered) fonts (17.28pt). -\def\chapnominalsize{17pt} -\setfont\chaprm\rmbshape{12}{\magstep2} -\setfont\chapit\itbshape{10}{\magstep3} -\setfont\chapsl\slbshape{10}{\magstep3} -\setfont\chaptt\ttbshape{12}{\magstep2} -\setfont\chapttsl\ttslshape{10}{\magstep3} -\setfont\chapsf\sfbshape{17}{1000} -\let\chapbf=\chaprm -\setfont\chapsc\scbshape{10}{\magstep3} -\font\chapi=cmmi12 scaled \magstep2 -\font\chapsy=cmsy10 scaled \magstep3 - -% Section fonts (14.4pt). -\def\secnominalsize{14pt} -\setfont\secrm\rmbshape{12}{\magstep1} -\setfont\secit\itbshape{10}{\magstep2} -\setfont\secsl\slbshape{10}{\magstep2} -\setfont\sectt\ttbshape{12}{\magstep1} -\setfont\secttsl\ttslshape{10}{\magstep2} -\setfont\secsf\sfbshape{12}{\magstep1} -\let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep2} -\font\seci=cmmi12 scaled \magstep1 -\font\secsy=cmsy10 scaled \magstep2 - -% Subsection fonts (13.15pt). -\def\ssecnominalsize{13pt} -\setfont\ssecrm\rmbshape{12}{\magstephalf} -\setfont\ssecit\itbshape{10}{1315} -\setfont\ssecsl\slbshape{10}{1315} -\setfont\ssectt\ttbshape{12}{\magstephalf} -\setfont\ssecttsl\ttslshape{10}{1315} -\setfont\ssecsf\sfbshape{12}{\magstephalf} -\let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{1315} -\font\sseci=cmmi12 scaled \magstephalf -\font\ssecsy=cmsy10 scaled 1315 - -% Reduced fonts for @acro in text (10pt). -\def\reducednominalsize{10pt} -\setfont\reducedrm\rmshape{10}{1000} -\setfont\reducedtt\ttshape{10}{1000} -\setfont\reducedbf\bfshape{10}{1000} -\setfont\reducedit\itshape{10}{1000} -\setfont\reducedsl\slshape{10}{1000} -\setfont\reducedsf\sfshape{10}{1000} -\setfont\reducedsc\scshape{10}{1000} -\setfont\reducedttsl\ttslshape{10}{1000} -\font\reducedi=cmmi10 -\font\reducedsy=cmsy10 - -% reset the current fonts -\textfonts -\rm -} % end of 11pt text font size definitions - - -% Definitions to make the main text be 10pt Computer Modern, with -% section, chapter, etc., sizes following suit. This is for the GNU -% Press printing of the Emacs 22 manual. Maybe other manuals in the -% future. Used with @smallbook, which sets the leading to 12pt. -% -\def\definetextfontsizex{% -% Text fonts (10pt). -\def\textnominalsize{10pt} -\edef\mainmagstep{1000} -\setfont\textrm\rmshape{10}{\mainmagstep} -\setfont\texttt\ttshape{10}{\mainmagstep} -\setfont\textbf\bfshape{10}{\mainmagstep} -\setfont\textit\itshape{10}{\mainmagstep} -\setfont\textsl\slshape{10}{\mainmagstep} -\setfont\textsf\sfshape{10}{\mainmagstep} -\setfont\textsc\scshape{10}{\mainmagstep} -\setfont\textttsl\ttslshape{10}{\mainmagstep} -\font\texti=cmmi10 scaled \mainmagstep -\font\textsy=cmsy10 scaled \mainmagstep - -% A few fonts for @defun names and args. -\setfont\defbf\bfshape{10}{\magstephalf} -\setfont\deftt\ttshape{10}{\magstephalf} -\setfont\defttsl\ttslshape{10}{\magstephalf} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} - -% Fonts for indices, footnotes, small examples (9pt). -\def\smallnominalsize{9pt} -\setfont\smallrm\rmshape{9}{1000} -\setfont\smalltt\ttshape{9}{1000} -\setfont\smallbf\bfshape{10}{900} -\setfont\smallit\itshape{9}{1000} -\setfont\smallsl\slshape{9}{1000} -\setfont\smallsf\sfshape{9}{1000} -\setfont\smallsc\scshape{10}{900} -\setfont\smallttsl\ttslshape{10}{900} -\font\smalli=cmmi9 -\font\smallsy=cmsy9 - -% Fonts for small examples (8pt). -\def\smallernominalsize{8pt} -\setfont\smallerrm\rmshape{8}{1000} -\setfont\smallertt\ttshape{8}{1000} -\setfont\smallerbf\bfshape{10}{800} -\setfont\smallerit\itshape{8}{1000} -\setfont\smallersl\slshape{8}{1000} -\setfont\smallersf\sfshape{8}{1000} -\setfont\smallersc\scshape{10}{800} -\setfont\smallerttsl\ttslshape{10}{800} -\font\smalleri=cmmi8 -\font\smallersy=cmsy8 - -% Fonts for title page (20.4pt): -\def\titlenominalsize{20pt} -\setfont\titlerm\rmbshape{12}{\magstep3} -\setfont\titleit\itbshape{10}{\magstep4} -\setfont\titlesl\slbshape{10}{\magstep4} -\setfont\titlett\ttbshape{12}{\magstep3} -\setfont\titlettsl\ttslshape{10}{\magstep4} -\setfont\titlesf\sfbshape{17}{\magstep1} -\let\titlebf=\titlerm -\setfont\titlesc\scbshape{10}{\magstep4} -\font\titlei=cmmi12 scaled \magstep3 -\font\titlesy=cmsy10 scaled \magstep4 -\def\authorrm{\secrm} -\def\authortt{\sectt} - -% Chapter fonts (14.4pt). -\def\chapnominalsize{14pt} -\setfont\chaprm\rmbshape{12}{\magstep1} -\setfont\chapit\itbshape{10}{\magstep2} -\setfont\chapsl\slbshape{10}{\magstep2} -\setfont\chaptt\ttbshape{12}{\magstep1} -\setfont\chapttsl\ttslshape{10}{\magstep2} -\setfont\chapsf\sfbshape{12}{\magstep1} -\let\chapbf\chaprm -\setfont\chapsc\scbshape{10}{\magstep2} -\font\chapi=cmmi12 scaled \magstep1 -\font\chapsy=cmsy10 scaled \magstep2 - -% Section fonts (12pt). -\def\secnominalsize{12pt} -\setfont\secrm\rmbshape{12}{1000} -\setfont\secit\itbshape{10}{\magstep1} -\setfont\secsl\slbshape{10}{\magstep1} -\setfont\sectt\ttbshape{12}{1000} -\setfont\secttsl\ttslshape{10}{\magstep1} -\setfont\secsf\sfbshape{12}{1000} -\let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep1} -\font\seci=cmmi12 -\font\secsy=cmsy10 scaled \magstep1 - -% Subsection fonts (10pt). -\def\ssecnominalsize{10pt} -\setfont\ssecrm\rmbshape{10}{1000} -\setfont\ssecit\itbshape{10}{1000} -\setfont\ssecsl\slbshape{10}{1000} -\setfont\ssectt\ttbshape{10}{1000} -\setfont\ssecttsl\ttslshape{10}{1000} -\setfont\ssecsf\sfbshape{10}{1000} -\let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{1000} -\font\sseci=cmmi10 -\font\ssecsy=cmsy10 - -% Reduced fonts for @acro in text (9pt). -\def\reducednominalsize{9pt} -\setfont\reducedrm\rmshape{9}{1000} -\setfont\reducedtt\ttshape{9}{1000} -\setfont\reducedbf\bfshape{10}{900} -\setfont\reducedit\itshape{9}{1000} -\setfont\reducedsl\slshape{9}{1000} -\setfont\reducedsf\sfshape{9}{1000} -\setfont\reducedsc\scshape{10}{900} -\setfont\reducedttsl\ttslshape{10}{900} -\font\reducedi=cmmi9 -\font\reducedsy=cmsy9 - -% reduce space between paragraphs -\divide\parskip by 2 - -% reset the current fonts -\textfonts -\rm -} % end of 10pt text font size definitions - - -% We provide the user-level command -% @fonttextsize 10 -% (or 11) to redefine the text font size. pt is assumed. -% -\def\xword{10} -\def\xiword{11} -% -\parseargdef\fonttextsize{% - \def\textsizearg{#1}% - \wlog{doing @fonttextsize \textsizearg}% - % - % Set \globaldefs so that documents can use this inside @tex, since - % makeinfo 4.8 does not support it, but we need it nonetheless. - % - \begingroup \globaldefs=1 - \ifx\textsizearg\xword \definetextfontsizex - \else \ifx\textsizearg\xiword \definetextfontsizexi - \else - \errhelp=\EMsimple - \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} - \fi\fi - \endgroup -} - - -% In order for the font changes to affect most math symbols and letters, -% we have to define the \textfont of the standard families. Since -% texinfo doesn't allow for producing subscripts and superscripts except -% in the main text, we don't bother to reset \scriptfont and -% \scriptscriptfont (which would also require loading a lot more fonts). -% -\def\resetmathfonts{% - \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy - \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf - \textfont\ttfam=\tentt \textfont\sffam=\tensf -} - -% The font-changing commands redefine the meanings of \tenSTYLE, instead -% of just \STYLE. We do this because \STYLE needs to also set the -% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire -% \tenSTYLE to set the current font. -% -% Each font-changing command also sets the names \lsize (one size lower) -% and \lllsize (three sizes lower). These relative commands are used in -% the LaTeX logo and acronyms. -% -% This all needs generalizing, badly. -% -\def\textfonts{% - \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl - \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc - \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy - \let\tenttsl=\textttsl - \def\curfontsize{text}% - \def\lsize{reduced}\def\lllsize{smaller}% - \resetmathfonts \setleading{\textleading}} -\def\titlefonts{% - \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl - \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc - \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy - \let\tenttsl=\titlettsl - \def\curfontsize{title}% - \def\lsize{chap}\def\lllsize{subsec}% - \resetmathfonts \setleading{25pt}} -\def\titlefont#1{{\titlefonts\rm #1}} -\def\chapfonts{% - \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl - \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc - \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy - \let\tenttsl=\chapttsl - \def\curfontsize{chap}% - \def\lsize{sec}\def\lllsize{text}% - \resetmathfonts \setleading{19pt}} -\def\secfonts{% - \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl - \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc - \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy - \let\tenttsl=\secttsl - \def\curfontsize{sec}% - \def\lsize{subsec}\def\lllsize{reduced}% - \resetmathfonts \setleading{16pt}} -\def\subsecfonts{% - \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl - \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc - \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy - \let\tenttsl=\ssecttsl - \def\curfontsize{ssec}% - \def\lsize{text}\def\lllsize{small}% - \resetmathfonts \setleading{15pt}} -\let\subsubsecfonts = \subsecfonts -\def\reducedfonts{% - \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl - \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc - \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy - \let\tenttsl=\reducedttsl - \def\curfontsize{reduced}% - \def\lsize{small}\def\lllsize{smaller}% - \resetmathfonts \setleading{10.5pt}} -\def\smallfonts{% - \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl - \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc - \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy - \let\tenttsl=\smallttsl - \def\curfontsize{small}% - \def\lsize{smaller}\def\lllsize{smaller}% - \resetmathfonts \setleading{10.5pt}} -\def\smallerfonts{% - \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl - \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc - \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy - \let\tenttsl=\smallerttsl - \def\curfontsize{smaller}% - \def\lsize{smaller}\def\lllsize{smaller}% - \resetmathfonts \setleading{9.5pt}} - -% Set the fonts to use with the @small... environments. -\let\smallexamplefonts = \smallfonts - -% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample -% can fit this many characters: -% 8.5x11=86 smallbook=72 a4=90 a5=69 -% If we use \scriptfonts (8pt), then we can fit this many characters: -% 8.5x11=90+ smallbook=80 a4=90+ a5=77 -% For me, subjectively, the few extra characters that fit aren't worth -% the additional smallness of 8pt. So I'm making the default 9pt. -% -% By the way, for comparison, here's what fits with @example (10pt): -% 8.5x11=71 smallbook=60 a4=75 a5=58 -% -% I wish the USA used A4 paper. -% --karl, 24jan03. - - -% Set up the default fonts, so we can use them for creating boxes. -% -\definetextfontsizexi - -% Define these so they can be easily changed for other fonts. -\def\angleleft{$\langle$} -\def\angleright{$\rangle$} - -% Count depth in font-changes, for error checks -\newcount\fontdepth \fontdepth=0 - -% Fonts for short table of contents. -\setfont\shortcontrm\rmshape{12}{1000} -\setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 -\setfont\shortcontsl\slshape{12}{1000} -\setfont\shortconttt\ttshape{12}{1000} - -%% Add scribe-like font environments, plus @l for inline lisp (usually sans -%% serif) and @ii for TeX italic - -% \smartitalic{ARG} outputs arg in italics, followed by an italic correction -% unless the following character is such as not to need one. -\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else - \ptexslash\fi\fi\fi} -\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} -\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} - -% like \smartslanted except unconditionally uses \ttsl. -% @var is set to this for defun arguments. -\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} - -% like \smartslanted except unconditionally use \sl. We never want -% ttsl for book titles, do we? -\def\cite#1{{\sl #1}\futurelet\next\smartitalicx} - -\let\i=\smartitalic -\let\slanted=\smartslanted -\let\var=\smartslanted -\let\dfn=\smartslanted -\let\emph=\smartitalic - -% @b, explicit bold. -\def\b#1{{\bf #1}} -\let\strong=\b - -% @sansserif, explicit sans. -\def\sansserif#1{{\sf #1}} - -% We can't just use \exhyphenpenalty, because that only has effect at -% the end of a paragraph. Restore normal hyphenation at the end of the -% group within which \nohyphenation is presumably called. -% -\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} -\def\restorehyphenation{\hyphenchar\font = `- } - -% Set sfcode to normal for the chars that usually have another value. -% Can't use plain's \frenchspacing because it uses the `\x notation, and -% sometimes \x has an active definition that messes things up. -% -\catcode`@=11 - \def\plainfrenchspacing{% - \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m - \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m - \def\endofsentencespacefactor{1000}% for @. and friends - } - \def\plainnonfrenchspacing{% - \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 - \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 - \def\endofsentencespacefactor{3000}% for @. and friends - } -\catcode`@=\other -\def\endofsentencespacefactor{3000}% default - -\def\t#1{% - {\tt \rawbackslash \plainfrenchspacing #1}% - \null -} -\def\samp#1{`\tclose{#1}'\null} -\setfont\keyrm\rmshape{8}{1000} -\font\keysy=cmsy9 -\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% - \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% - \vbox{\hrule\kern-0.4pt - \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% - \kern-0.4pt\hrule}% - \kern-.06em\raise0.4pt\hbox{\angleright}}}} -\def\key #1{{\nohyphenation \uppercase{#1}}\null} -% The old definition, with no lozenge: -%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} -\def\ctrl #1{{\tt \rawbackslash \hat}#1} - -% @file, @option are the same as @samp. -\let\file=\samp -\let\option=\samp - -% @code is a modification of @t, -% which makes spaces the same size as normal in the surrounding text. -\def\tclose#1{% - {% - % Change normal interword space to be same as for the current font. - \spaceskip = \fontdimen2\font - % - % Switch to typewriter. - \tt - % - % But `\ ' produces the large typewriter interword space. - \def\ {{\spaceskip = 0pt{} }}% - % - % Turn off hyphenation. - \nohyphenation - % - \rawbackslash - \plainfrenchspacing - #1% - }% - \null -} - -% We *must* turn on hyphenation at `-' and `_' in @code. -% Otherwise, it is too hard to avoid overfull hboxes -% in the Emacs manual, the Library manual, etc. - -% Unfortunately, TeX uses one parameter (\hyphenchar) to control -% both hyphenation at - and hyphenation within words. -% We must therefore turn them both off (\tclose does that) -% and arrange explicitly to hyphenate at a dash. -% -- rms. -{ - \catcode`\-=\active \catcode`\_=\active - \catcode`\'=\active \catcode`\`=\active - % - \global\def\code{\begingroup - \catcode\rquoteChar=\active \catcode\lquoteChar=\active - \let'\codequoteright \let`\codequoteleft - % - \catcode\dashChar=\active \catcode\underChar=\active - \ifallowcodebreaks - \let-\codedash - \let_\codeunder - \else - \let-\realdash - \let_\realunder - \fi - \codex - } -} - -\def\realdash{-} -\def\codedash{-\discretionary{}{}{}} -\def\codeunder{% - % this is all so @math{@code{var_name}+1} can work. In math mode, _ - % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) - % will therefore expand the active definition of _, which is us - % (inside @code that is), therefore an endless loop. - \ifusingtt{\ifmmode - \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. - \else\normalunderscore \fi - \discretionary{}{}{}}% - {\_}% -} -\def\codex #1{\tclose{#1}\endgroup} - -% An additional complication: the above will allow breaks after, e.g., -% each of the four underscores in __typeof__. This is undesirable in -% some manuals, especially if they don't have long identifiers in -% general. @allowcodebreaks provides a way to control this. -% -\newif\ifallowcodebreaks \allowcodebreakstrue - -\def\keywordtrue{true} -\def\keywordfalse{false} - -\parseargdef\allowcodebreaks{% - \def\txiarg{#1}% - \ifx\txiarg\keywordtrue - \allowcodebreakstrue - \else\ifx\txiarg\keywordfalse - \allowcodebreaksfalse - \else - \errhelp = \EMsimple - \errmessage{Unknown @allowcodebreaks option `\txiarg'}% - \fi\fi -} - -% @kbd is like @code, except that if the argument is just one @key command, -% then @kbd has no effect. - -% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), -% `example' (@kbd uses ttsl only inside of @example and friends), -% or `code' (@kbd uses normal tty font always). -\parseargdef\kbdinputstyle{% - \def\txiarg{#1}% - \ifx\txiarg\worddistinct - \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% - \else\ifx\txiarg\wordexample - \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% - \else\ifx\txiarg\wordcode - \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% - \else - \errhelp = \EMsimple - \errmessage{Unknown @kbdinputstyle option `\txiarg'}% - \fi\fi\fi -} -\def\worddistinct{distinct} -\def\wordexample{example} -\def\wordcode{code} - -% Default is `distinct.' -\kbdinputstyle distinct - -\def\xkey{\key} -\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% -\ifx\one\xkey\ifx\threex\three \key{#2}% -\else{\tclose{\kbdfont\look}}\fi -\else{\tclose{\kbdfont\look}}\fi} - -% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. -\let\indicateurl=\code -\let\env=\code -\let\command=\code - -% @uref (abbreviation for `urlref') takes an optional (comma-separated) -% second argument specifying the text to display and an optional third -% arg as text to display instead of (rather than in addition to) the url -% itself. First (mandatory) arg is the url. Perhaps eventually put in -% a hypertex \special here. -% -\def\uref#1{\douref #1,,,\finish} -\def\douref#1,#2,#3,#4\finish{\begingroup - \unsepspaces - \pdfurl{#1}% - \setbox0 = \hbox{\ignorespaces #3}% - \ifdim\wd0 > 0pt - \unhbox0 % third arg given, show only that - \else - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \ifpdf - \unhbox0 % PDF: 2nd arg given, show only it - \else - \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url - \fi - \else - \code{#1}% only url given, so show it - \fi - \fi - \endlink -\endgroup} - -% @url synonym for @uref, since that's how everyone uses it. -% -\let\url=\uref - -% rms does not like angle brackets --karl, 17may97. -% So now @email is just like @uref, unless we are pdf. -% -%\def\email#1{\angleleft{\tt #1}\angleright} -\ifpdf - \def\email#1{\doemail#1,,\finish} - \def\doemail#1,#2,#3\finish{\begingroup - \unsepspaces - \pdfurl{mailto:#1}% - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi - \endlink - \endgroup} -\else - \let\email=\uref -\fi - -% Check if we are currently using a typewriter font. Since all the -% Computer Modern typewriter fonts have zero interword stretch (and -% shrink), and it is reasonable to expect all typewriter fonts to have -% this property, we can check that font parameter. -% -\def\ifmonospace{\ifdim\fontdimen3\font=0pt } - -% Typeset a dimension, e.g., `in' or `pt'. The only reason for the -% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. -% -\def\dmn#1{\thinspace #1} - -\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} - -% @l was never documented to mean ``switch to the Lisp font'', -% and it is not used as such in any manual I can find. We need it for -% Polish suppressed-l. --karl, 22sep96. -%\def\l#1{{\li #1}\null} - -% Explicit font changes: @r, @sc, undocumented @ii. -\def\r#1{{\rm #1}} % roman font -\def\sc#1{{\smallcaps#1}} % smallcaps font -\def\ii#1{{\it #1}} % italic font - -% @acronym for "FBI", "NATO", and the like. -% We print this one point size smaller, since it's intended for -% all-uppercase. -% -\def\acronym#1{\doacronym #1,,\finish} -\def\doacronym#1,#2,#3\finish{% - {\selectfonts\lsize #1}% - \def\temp{#2}% - \ifx\temp\empty \else - \space ({\unsepspaces \ignorespaces \temp \unskip})% - \fi -} - -% @abbr for "Comput. J." and the like. -% No font change, but don't do end-of-sentence spacing. -% -\def\abbr#1{\doabbr #1,,\finish} -\def\doabbr#1,#2,#3\finish{% - {\plainfrenchspacing #1}% - \def\temp{#2}% - \ifx\temp\empty \else - \space ({\unsepspaces \ignorespaces \temp \unskip})% - \fi -} - -% @pounds{} is a sterling sign, which Knuth put in the CM italic font. -% -\def\pounds{{\it\$}} - -% @euro{} comes from a separate font, depending on the current style. -% We use the free feym* fonts from the eurosym package by Henrik -% Theiling, which support regular, slanted, bold and bold slanted (and -% "outlined" (blackboard board, sort of) versions, which we don't need). -% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. -% -% Although only regular is the truly official Euro symbol, we ignore -% that. The Euro is designed to be slightly taller than the regular -% font height. -% -% feymr - regular -% feymo - slanted -% feybr - bold -% feybo - bold slanted -% -% There is no good (free) typewriter version, to my knowledge. -% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. -% Hmm. -% -% Also doesn't work in math. Do we need to do math with euro symbols? -% Hope not. -% -% -\def\euro{{\eurofont e}} -\def\eurofont{% - % We set the font at each command, rather than predefining it in - % \textfonts and the other font-switching commands, so that - % installations which never need the symbol don't have to have the - % font installed. - % - % There is only one designed size (nominal 10pt), so we always scale - % that to the current nominal size. - % - % By the way, simply using "at 1em" works for cmr10 and the like, but - % does not work for cmbx10 and other extended/shrunken fonts. - % - \def\eurosize{\csname\curfontsize nominalsize\endcsname}% - % - \ifx\curfontstyle\bfstylename - % bold: - \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize - \else - % regular: - \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize - \fi - \thiseurofont -} - -% @registeredsymbol - R in a circle. The font for the R should really -% be smaller yet, but lllsize is the best we can do for now. -% Adapted from the plain.tex definition of \copyright. -% -\def\registeredsymbol{% - $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% - \hfil\crcr\Orb}}% - }$% -} - -% @textdegree - the normal degrees sign. -% -\def\textdegree{$^\circ$} - -% Laurent Siebenmann reports \Orb undefined with: -% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 -% so we'll define it if necessary. -% -\ifx\Orb\undefined -\def\Orb{\mathhexbox20D} -\fi - - -\message{page headings,} - -\newskip\titlepagetopglue \titlepagetopglue = 1.5in -\newskip\titlepagebottomglue \titlepagebottomglue = 2pc - -% First the title page. Must do @settitle before @titlepage. -\newif\ifseenauthor -\newif\iffinishedtitlepage - -% Do an implicit @contents or @shortcontents after @end titlepage if the -% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. -% -\newif\ifsetcontentsaftertitlepage - \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue -\newif\ifsetshortcontentsaftertitlepage - \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue - -\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% - \endgroup\page\hbox{}\page} - -\envdef\titlepage{% - % Open one extra group, as we want to close it in the middle of \Etitlepage. - \begingroup - \parindent=0pt \textfonts - % Leave some space at the very top of the page. - \vglue\titlepagetopglue - % No rule at page bottom unless we print one at the top with @title. - \finishedtitlepagetrue - % - % Most title ``pages'' are actually two pages long, with space - % at the top of the second. We don't want the ragged left on the second. - \let\oldpage = \page - \def\page{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - \let\page = \oldpage - \page - \null - }% -} - -\def\Etitlepage{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - % It is important to do the page break before ending the group, - % because the headline and footline are only empty inside the group. - % If we use the new definition of \page, we always get a blank page - % after the title page, which we certainly don't want. - \oldpage - \endgroup - % - % Need this before the \...aftertitlepage checks so that if they are - % in effect the toc pages will come out with page numbers. - \HEADINGSon - % - % If they want short, they certainly want long too. - \ifsetshortcontentsaftertitlepage - \shortcontents - \contents - \global\let\shortcontents = \relax - \global\let\contents = \relax - \fi - % - \ifsetcontentsaftertitlepage - \contents - \global\let\contents = \relax - \global\let\shortcontents = \relax - \fi -} - -\def\finishtitlepage{% - \vskip4pt \hrule height 2pt width \hsize - \vskip\titlepagebottomglue - \finishedtitlepagetrue -} - -%%% Macros to be used within @titlepage: - -\let\subtitlerm=\tenrm -\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} - -\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines - \let\tt=\authortt} - -\parseargdef\title{% - \checkenv\titlepage - \leftline{\titlefonts\rm #1} - % print a rule at the page bottom also. - \finishedtitlepagefalse - \vskip4pt \hrule height 4pt width \hsize \vskip4pt -} - -\parseargdef\subtitle{% - \checkenv\titlepage - {\subtitlefont \rightline{#1}}% -} - -% @author should come last, but may come many times. -% It can also be used inside @quotation. -% -\parseargdef\author{% - \def\temp{\quotation}% - \ifx\thisenv\temp - \def\quotationauthor{#1}% printed in \Equotation. - \else - \checkenv\titlepage - \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi - {\authorfont \leftline{#1}}% - \fi -} - - -%%% Set up page headings and footings. - -\let\thispage=\folio - -\newtoks\evenheadline % headline on even pages -\newtoks\oddheadline % headline on odd pages -\newtoks\evenfootline % footline on even pages -\newtoks\oddfootline % footline on odd pages - -% Now make TeX use those variables -\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline - \else \the\evenheadline \fi}} -\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline - \else \the\evenfootline \fi}\HEADINGShook} -\let\HEADINGShook=\relax - -% Commands to set those variables. -% For example, this is what @headings on does -% @evenheading @thistitle|@thispage|@thischapter -% @oddheading @thischapter|@thispage|@thistitle -% @evenfooting @thisfile|| -% @oddfooting ||@thisfile - - -\def\evenheading{\parsearg\evenheadingxxx} -\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} -\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% -\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\def\oddheading{\parsearg\oddheadingxxx} -\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} -\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% -\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% - -\def\evenfooting{\parsearg\evenfootingxxx} -\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} -\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% -\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\def\oddfooting{\parsearg\oddfootingxxx} -\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} -\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% - \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% - % - % Leave some space for the footline. Hopefully ok to assume - % @evenfooting will not be used by itself. - \global\advance\pageheight by -12pt - \global\advance\vsize by -12pt -} - -\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} - - -% @headings double turns headings on for double-sided printing. -% @headings single turns headings on for single-sided printing. -% @headings off turns them off. -% @headings on same as @headings double, retained for compatibility. -% @headings after turns on double-sided headings after this page. -% @headings doubleafter turns on double-sided headings after this page. -% @headings singleafter turns on single-sided headings after this page. -% By default, they are off at the start of a document, -% and turned `on' after @end titlepage. - -\def\headings #1 {\csname HEADINGS#1\endcsname} - -\def\HEADINGSoff{% -\global\evenheadline={\hfil} \global\evenfootline={\hfil} -\global\oddheadline={\hfil} \global\oddfootline={\hfil}} -\HEADINGSoff -% When we turn headings on, set the page number to 1. -% For double-sided printing, put current file name in lower left corner, -% chapter name on inside top of right hand pages, document -% title on inside top of left hand pages, and page numbers on outside top -% edge of all pages. -\def\HEADINGSdouble{% -\global\pageno=1 -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chapoddpage -} -\let\contentsalignmacro = \chappager - -% For single-sided printing, chapter title goes across top left of page, -% page number on top right. -\def\HEADINGSsingle{% -\global\pageno=1 -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chappager -} -\def\HEADINGSon{\HEADINGSdouble} - -\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} -\let\HEADINGSdoubleafter=\HEADINGSafter -\def\HEADINGSdoublex{% -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chapoddpage -} - -\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} -\def\HEADINGSsinglex{% -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chappager -} - -% Subroutines used in generating headings -% This produces Day Month Year style of output. -% Only define if not already defined, in case a txi-??.tex file has set -% up a different format (e.g., txi-cs.tex does this). -\ifx\today\undefined -\def\today{% - \number\day\space - \ifcase\month - \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr - \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug - \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec - \fi - \space\number\year} -\fi - -% @settitle line... specifies the title of the document, for headings. -% It generates no output of its own. -\def\thistitle{\putwordNoTitle} -\def\settitle{\parsearg{\gdef\thistitle}} - - -\message{tables,} -% Tables -- @table, @ftable, @vtable, @item(x). - -% default indentation of table text -\newdimen\tableindent \tableindent=.8in -% default indentation of @itemize and @enumerate text -\newdimen\itemindent \itemindent=.3in -% margin between end of table item and start of table text. -\newdimen\itemmargin \itemmargin=.1in - -% used internally for \itemindent minus \itemmargin -\newdimen\itemmax - -% Note @table, @ftable, and @vtable define @item, @itemx, etc., with -% these defs. -% They also define \itemindex -% to index the item name in whatever manner is desired (perhaps none). - -\newif\ifitemxneedsnegativevskip - -\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} - -\def\internalBitem{\smallbreak \parsearg\itemzzz} -\def\internalBitemx{\itemxpar \parsearg\itemzzz} - -\def\itemzzz #1{\begingroup % - \advance\hsize by -\rightskip - \advance\hsize by -\tableindent - \setbox0=\hbox{\itemindicate{#1}}% - \itemindex{#1}% - \nobreak % This prevents a break before @itemx. - % - % If the item text does not fit in the space we have, put it on a line - % by itself, and do not allow a page break either before or after that - % line. We do not start a paragraph here because then if the next - % command is, e.g., @kindex, the whatsit would get put into the - % horizontal list on a line by itself, resulting in extra blank space. - \ifdim \wd0>\itemmax - % - % Make this a paragraph so we get the \parskip glue and wrapping, - % but leave it ragged-right. - \begingroup - \advance\leftskip by-\tableindent - \advance\hsize by\tableindent - \advance\rightskip by0pt plus1fil - \leavevmode\unhbox0\par - \endgroup - % - % We're going to be starting a paragraph, but we don't want the - % \parskip glue -- logically it's part of the @item we just started. - \nobreak \vskip-\parskip - % - % Stop a page break at the \parskip glue coming up. However, if - % what follows is an environment such as @example, there will be no - % \parskip glue; then the negative vskip we just inserted would - % cause the example and the item to crash together. So we use this - % bizarre value of 10001 as a signal to \aboveenvbreak to insert - % \parskip glue after all. Section titles are handled this way also. - % - \penalty 10001 - \endgroup - \itemxneedsnegativevskipfalse - \else - % The item text fits into the space. Start a paragraph, so that the - % following text (if any) will end up on the same line. - \noindent - % Do this with kerns and \unhbox so that if there is a footnote in - % the item text, it can migrate to the main vertical list and - % eventually be printed. - \nobreak\kern-\tableindent - \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 - \unhbox0 - \nobreak\kern\dimen0 - \endgroup - \itemxneedsnegativevskiptrue - \fi -} - -\def\item{\errmessage{@item while not in a list environment}} -\def\itemx{\errmessage{@itemx while not in a list environment}} - -% @table, @ftable, @vtable. -\envdef\table{% - \let\itemindex\gobble - \tablecheck{table}% -} -\envdef\ftable{% - \def\itemindex ##1{\doind {fn}{\code{##1}}}% - \tablecheck{ftable}% -} -\envdef\vtable{% - \def\itemindex ##1{\doind {vr}{\code{##1}}}% - \tablecheck{vtable}% -} -\def\tablecheck#1{% - \ifnum \the\catcode`\^^M=\active - \endgroup - \errmessage{This command won't work in this context; perhaps the problem is - that we are \inenvironment\thisenv}% - \def\next{\doignore{#1}}% - \else - \let\next\tablex - \fi - \next -} -\def\tablex#1{% - \def\itemindicate{#1}% - \parsearg\tabley -} -\def\tabley#1{% - {% - \makevalueexpandable - \edef\temp{\noexpand\tablez #1\space\space\space}% - \expandafter - }\temp \endtablez -} -\def\tablez #1 #2 #3 #4\endtablez{% - \aboveenvbreak - \ifnum 0#1>0 \advance \leftskip by #1\mil \fi - \ifnum 0#2>0 \tableindent=#2\mil \fi - \ifnum 0#3>0 \advance \rightskip by #3\mil \fi - \itemmax=\tableindent - \advance \itemmax by -\itemmargin - \advance \leftskip by \tableindent - \exdentamount=\tableindent - \parindent = 0pt - \parskip = \smallskipamount - \ifdim \parskip=0pt \parskip=2pt \fi - \let\item = \internalBitem - \let\itemx = \internalBitemx -} -\def\Etable{\endgraf\afterenvbreak} -\let\Eftable\Etable -\let\Evtable\Etable -\let\Eitemize\Etable -\let\Eenumerate\Etable - -% This is the counter used by @enumerate, which is really @itemize - -\newcount \itemno - -\envdef\itemize{\parsearg\doitemize} - -\def\doitemize#1{% - \aboveenvbreak - \itemmax=\itemindent - \advance\itemmax by -\itemmargin - \advance\leftskip by \itemindent - \exdentamount=\itemindent - \parindent=0pt - \parskip=\smallskipamount - \ifdim\parskip=0pt \parskip=2pt \fi - \def\itemcontents{#1}% - % @itemize with no arg is equivalent to @itemize @bullet. - \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi - \let\item=\itemizeitem -} - -% Definition of @item while inside @itemize and @enumerate. -% -\def\itemizeitem{% - \advance\itemno by 1 % for enumerations - {\let\par=\endgraf \smallbreak}% reasonable place to break - {% - % If the document has an @itemize directly after a section title, a - % \nobreak will be last on the list, and \sectionheading will have - % done a \vskip-\parskip. In that case, we don't want to zero - % parskip, or the item text will crash with the heading. On the - % other hand, when there is normal text preceding the item (as there - % usually is), we do want to zero parskip, or there would be too much - % space. In that case, we won't have a \nobreak before. At least - % that's the theory. - \ifnum\lastpenalty<10000 \parskip=0in \fi - \noindent - \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% - \vadjust{\penalty 1200}}% not good to break after first line of item. - \flushcr -} - -% \splitoff TOKENS\endmark defines \first to be the first token in -% TOKENS, and \rest to be the remainder. -% -\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% - -% Allow an optional argument of an uppercase letter, lowercase letter, -% or number, to specify the first label in the enumerated list. No -% argument is the same as `1'. -% -\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} -\def\enumeratey #1 #2\endenumeratey{% - % If we were given no argument, pretend we were given `1'. - \def\thearg{#1}% - \ifx\thearg\empty \def\thearg{1}\fi - % - % Detect if the argument is a single token. If so, it might be a - % letter. Otherwise, the only valid thing it can be is a number. - % (We will always have one token, because of the test we just made. - % This is a good thing, since \splitoff doesn't work given nothing at - % all -- the first parameter is undelimited.) - \expandafter\splitoff\thearg\endmark - \ifx\rest\empty - % Only one token in the argument. It could still be anything. - % A ``lowercase letter'' is one whose \lccode is nonzero. - % An ``uppercase letter'' is one whose \lccode is both nonzero, and - % not equal to itself. - % Otherwise, we assume it's a number. - % - % We need the \relax at the end of the \ifnum lines to stop TeX from - % continuing to look for a . - % - \ifnum\lccode\expandafter`\thearg=0\relax - \numericenumerate % a number (we hope) - \else - % It's a letter. - \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax - \lowercaseenumerate % lowercase letter - \else - \uppercaseenumerate % uppercase letter - \fi - \fi - \else - % Multiple tokens in the argument. We hope it's a number. - \numericenumerate - \fi -} - -% An @enumerate whose labels are integers. The starting integer is -% given in \thearg. -% -\def\numericenumerate{% - \itemno = \thearg - \startenumeration{\the\itemno}% -} - -% The starting (lowercase) letter is in \thearg. -\def\lowercaseenumerate{% - \itemno = \expandafter`\thearg - \startenumeration{% - % Be sure we're not beyond the end of the alphabet. - \ifnum\itemno=0 - \errmessage{No more lowercase letters in @enumerate; get a bigger - alphabet}% - \fi - \char\lccode\itemno - }% -} - -% The starting (uppercase) letter is in \thearg. -\def\uppercaseenumerate{% - \itemno = \expandafter`\thearg - \startenumeration{% - % Be sure we're not beyond the end of the alphabet. - \ifnum\itemno=0 - \errmessage{No more uppercase letters in @enumerate; get a bigger - alphabet} - \fi - \char\uccode\itemno - }% -} - -% Call \doitemize, adding a period to the first argument and supplying the -% common last two arguments. Also subtract one from the initial value in -% \itemno, since @item increments \itemno. -% -\def\startenumeration#1{% - \advance\itemno by -1 - \doitemize{#1.}\flushcr -} - -% @alphaenumerate and @capsenumerate are abbreviations for giving an arg -% to @enumerate. -% -\def\alphaenumerate{\enumerate{a}} -\def\capsenumerate{\enumerate{A}} -\def\Ealphaenumerate{\Eenumerate} -\def\Ecapsenumerate{\Eenumerate} - - -% @multitable macros -% Amy Hendrickson, 8/18/94, 3/6/96 -% -% @multitable ... @end multitable will make as many columns as desired. -% Contents of each column will wrap at width given in preamble. Width -% can be specified either with sample text given in a template line, -% or in percent of \hsize, the current width of text on page. - -% Table can continue over pages but will only break between lines. - -% To make preamble: -% -% Either define widths of columns in terms of percent of \hsize: -% @multitable @columnfractions .25 .3 .45 -% @item ... -% -% Numbers following @columnfractions are the percent of the total -% current hsize to be used for each column. You may use as many -% columns as desired. - - -% Or use a template: -% @multitable {Column 1 template} {Column 2 template} {Column 3 template} -% @item ... -% using the widest term desired in each column. - -% Each new table line starts with @item, each subsequent new column -% starts with @tab. Empty columns may be produced by supplying @tab's -% with nothing between them for as many times as empty columns are needed, -% ie, @tab@tab@tab will produce two empty columns. - -% @item, @tab do not need to be on their own lines, but it will not hurt -% if they are. - -% Sample multitable: - -% @multitable {Column 1 template} {Column 2 template} {Column 3 template} -% @item first col stuff @tab second col stuff @tab third col -% @item -% first col stuff -% @tab -% second col stuff -% @tab -% third col -% @item first col stuff @tab second col stuff -% @tab Many paragraphs of text may be used in any column. -% -% They will wrap at the width determined by the template. -% @item@tab@tab This will be in third column. -% @end multitable - -% Default dimensions may be reset by user. -% @multitableparskip is vertical space between paragraphs in table. -% @multitableparindent is paragraph indent in table. -% @multitablecolmargin is horizontal space to be left between columns. -% @multitablelinespace is space to leave between table items, baseline -% to baseline. -% 0pt means it depends on current normal line spacing. -% -\newskip\multitableparskip -\newskip\multitableparindent -\newdimen\multitablecolspace -\newskip\multitablelinespace -\multitableparskip=0pt -\multitableparindent=6pt -\multitablecolspace=12pt -\multitablelinespace=0pt - -% Macros used to set up halign preamble: -% -\let\endsetuptable\relax -\def\xendsetuptable{\endsetuptable} -\let\columnfractions\relax -\def\xcolumnfractions{\columnfractions} -\newif\ifsetpercent - -% #1 is the @columnfraction, usually a decimal number like .5, but might -% be just 1. We just use it, whatever it is. -% -\def\pickupwholefraction#1 {% - \global\advance\colcount by 1 - \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% - \setuptable -} - -\newcount\colcount -\def\setuptable#1{% - \def\firstarg{#1}% - \ifx\firstarg\xendsetuptable - \let\go = \relax - \else - \ifx\firstarg\xcolumnfractions - \global\setpercenttrue - \else - \ifsetpercent - \let\go\pickupwholefraction - \else - \global\advance\colcount by 1 - \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a - % separator; typically that is always in the input, anyway. - \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% - \fi - \fi - \ifx\go\pickupwholefraction - % Put the argument back for the \pickupwholefraction call, so - % we'll always have a period there to be parsed. - \def\go{\pickupwholefraction#1}% - \else - \let\go = \setuptable - \fi% - \fi - \go -} - -% multitable-only commands. -% -% @headitem starts a heading row, which we typeset in bold. -% Assignments have to be global since we are inside the implicit group -% of an alignment entry. Note that \everycr resets \everytab. -\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% -% -% A \tab used to include \hskip1sp. But then the space in a template -% line is not enough. That is bad. So let's go back to just `&' until -% we encounter the problem it was intended to solve again. -% --karl, nathan@acm.org, 20apr99. -\def\tab{\checkenv\multitable &\the\everytab}% - -% @multitable ... @end multitable definitions: -% -\newtoks\everytab % insert after every tab. -% -\envdef\multitable{% - \vskip\parskip - \startsavinginserts - % - % @item within a multitable starts a normal row. - % We use \def instead of \let so that if one of the multitable entries - % contains an @itemize, we don't choke on the \item (seen as \crcr aka - % \endtemplate) expanding \doitemize. - \def\item{\crcr}% - % - \tolerance=9500 - \hbadness=9500 - \setmultitablespacing - \parskip=\multitableparskip - \parindent=\multitableparindent - \overfullrule=0pt - \global\colcount=0 - % - \everycr = {% - \noalign{% - \global\everytab={}% - \global\colcount=0 % Reset the column counter. - % Check for saved footnotes, etc. - \checkinserts - % Keeps underfull box messages off when table breaks over pages. - %\filbreak - % Maybe so, but it also creates really weird page breaks when the - % table breaks over pages. Wouldn't \vfil be better? Wait until the - % problem manifests itself, so it can be fixed for real --karl. - }% - }% - % - \parsearg\domultitable -} -\def\domultitable#1{% - % To parse everything between @multitable and @item: - \setuptable#1 \endsetuptable - % - % This preamble sets up a generic column definition, which will - % be used as many times as user calls for columns. - % \vtop will set a single line and will also let text wrap and - % continue for many paragraphs if desired. - \halign\bgroup &% - \global\advance\colcount by 1 - \multistrut - \vtop{% - % Use the current \colcount to find the correct column width: - \hsize=\expandafter\csname col\the\colcount\endcsname - % - % In order to keep entries from bumping into each other - % we will add a \leftskip of \multitablecolspace to all columns after - % the first one. - % - % If a template has been used, we will add \multitablecolspace - % to the width of each template entry. - % - % If the user has set preamble in terms of percent of \hsize we will - % use that dimension as the width of the column, and the \leftskip - % will keep entries from bumping into each other. Table will start at - % left margin and final column will justify at right margin. - % - % Make sure we don't inherit \rightskip from the outer environment. - \rightskip=0pt - \ifnum\colcount=1 - % The first column will be indented with the surrounding text. - \advance\hsize by\leftskip - \else - \ifsetpercent \else - % If user has not set preamble in terms of percent of \hsize - % we will advance \hsize by \multitablecolspace. - \advance\hsize by \multitablecolspace - \fi - % In either case we will make \leftskip=\multitablecolspace: - \leftskip=\multitablecolspace - \fi - % Ignoring space at the beginning and end avoids an occasional spurious - % blank line, when TeX decides to break the line at the space before the - % box from the multistrut, so the strut ends up on a line by itself. - % For example: - % @multitable @columnfractions .11 .89 - % @item @code{#} - % @tab Legal holiday which is valid in major parts of the whole country. - % Is automatically provided with highlighting sequences respectively - % marking characters. - \noindent\ignorespaces##\unskip\multistrut - }\cr -} -\def\Emultitable{% - \crcr - \egroup % end the \halign - \global\setpercentfalse -} - -\def\setmultitablespacing{% - \def\multistrut{\strut}% just use the standard line spacing - % - % Compute \multitablelinespace (if not defined by user) for use in - % \multitableparskip calculation. We used define \multistrut based on - % this, but (ironically) that caused the spacing to be off. - % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. -\ifdim\multitablelinespace=0pt -\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip -\global\advance\multitablelinespace by-\ht0 -\fi -%% Test to see if parskip is larger than space between lines of -%% table. If not, do nothing. -%% If so, set to same dimension as multitablelinespace. -\ifdim\multitableparskip>\multitablelinespace -\global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. -\fi% -\ifdim\multitableparskip=0pt -\global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. -\fi} - - -\message{conditionals,} - -% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, -% @ifnotxml always succeed. They currently do nothing; we don't -% attempt to check whether the conditionals are properly nested. But we -% have to remember that they are conditionals, so that @end doesn't -% attempt to close an environment group. -% -\def\makecond#1{% - \expandafter\let\csname #1\endcsname = \relax - \expandafter\let\csname iscond.#1\endcsname = 1 -} -\makecond{iftex} -\makecond{ifnotdocbook} -\makecond{ifnothtml} -\makecond{ifnotinfo} -\makecond{ifnotplaintext} -\makecond{ifnotxml} - -% Ignore @ignore, @ifhtml, @ifinfo, and the like. -% -\def\direntry{\doignore{direntry}} -\def\documentdescription{\doignore{documentdescription}} -\def\docbook{\doignore{docbook}} -\def\html{\doignore{html}} -\def\ifdocbook{\doignore{ifdocbook}} -\def\ifhtml{\doignore{ifhtml}} -\def\ifinfo{\doignore{ifinfo}} -\def\ifnottex{\doignore{ifnottex}} -\def\ifplaintext{\doignore{ifplaintext}} -\def\ifxml{\doignore{ifxml}} -\def\ignore{\doignore{ignore}} -\def\menu{\doignore{menu}} -\def\xml{\doignore{xml}} - -% Ignore text until a line `@end #1', keeping track of nested conditionals. -% -% A count to remember the depth of nesting. -\newcount\doignorecount - -\def\doignore#1{\begingroup - % Scan in ``verbatim'' mode: - \obeylines - \catcode`\@ = \other - \catcode`\{ = \other - \catcode`\} = \other - % - % Make sure that spaces turn into tokens that match what \doignoretext wants. - \spaceisspace - % - % Count number of #1's that we've seen. - \doignorecount = 0 - % - % Swallow text until we reach the matching `@end #1'. - \dodoignore{#1}% -} - -{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. - \obeylines % - % - \gdef\dodoignore#1{% - % #1 contains the command name as a string, e.g., `ifinfo'. - % - % Define a command to find the next `@end #1'. - \long\def\doignoretext##1^^M@end #1{% - \doignoretextyyy##1^^M@#1\_STOP_}% - % - % And this command to find another #1 command, at the beginning of a - % line. (Otherwise, we would consider a line `@c @ifset', for - % example, to count as an @ifset for nesting.) - \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% - % - % And now expand that command. - \doignoretext ^^M% - }% -} - -\def\doignoreyyy#1{% - \def\temp{#1}% - \ifx\temp\empty % Nothing found. - \let\next\doignoretextzzz - \else % Found a nested condition, ... - \advance\doignorecount by 1 - \let\next\doignoretextyyy % ..., look for another. - % If we're here, #1 ends with ^^M\ifinfo (for example). - \fi - \next #1% the token \_STOP_ is present just after this macro. -} - -% We have to swallow the remaining "\_STOP_". -% -\def\doignoretextzzz#1{% - \ifnum\doignorecount = 0 % We have just found the outermost @end. - \let\next\enddoignore - \else % Still inside a nested condition. - \advance\doignorecount by -1 - \let\next\doignoretext % Look for the next @end. - \fi - \next -} - -% Finish off ignored text. -{ \obeylines% - % Ignore anything after the last `@end #1'; this matters in verbatim - % environments, where otherwise the newline after an ignored conditional - % would result in a blank line in the output. - \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% -} - - -% @set VAR sets the variable VAR to an empty value. -% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. -% -% Since we want to separate VAR from REST-OF-LINE (which might be -% empty), we can't just use \parsearg; we have to insert a space of our -% own to delimit the rest of the line, and then take it out again if we -% didn't need it. -% We rely on the fact that \parsearg sets \catcode`\ =10. -% -\parseargdef\set{\setyyy#1 \endsetyyy} -\def\setyyy#1 #2\endsetyyy{% - {% - \makevalueexpandable - \def\temp{#2}% - \edef\next{\gdef\makecsname{SET#1}}% - \ifx\temp\empty - \next{}% - \else - \setzzz#2\endsetzzz - \fi - }% -} -% Remove the trailing space \setxxx inserted. -\def\setzzz#1 \endsetzzz{\next{#1}} - -% @clear VAR clears (i.e., unsets) the variable VAR. -% -\parseargdef\clear{% - {% - \makevalueexpandable - \global\expandafter\let\csname SET#1\endcsname=\relax - }% -} - -% @value{foo} gets the text saved in variable foo. -\def\value{\begingroup\makevalueexpandable\valuexxx} -\def\valuexxx#1{\expandablevalue{#1}\endgroup} -{ - \catcode`\- = \active \catcode`\_ = \active - % - \gdef\makevalueexpandable{% - \let\value = \expandablevalue - % We don't want these characters active, ... - \catcode`\-=\other \catcode`\_=\other - % ..., but we might end up with active ones in the argument if - % we're called from @code, as @code{@value{foo-bar_}}, though. - % So \let them to their normal equivalents. - \let-\realdash \let_\normalunderscore - } -} - -% We have this subroutine so that we can handle at least some @value's -% properly in indexes (we call \makevalueexpandable in \indexdummies). -% The command has to be fully expandable (if the variable is set), since -% the result winds up in the index file. This means that if the -% variable's value contains other Texinfo commands, it's almost certain -% it will fail (although perhaps we could fix that with sufficient work -% to do a one-level expansion on the result, instead of complete). -% -\def\expandablevalue#1{% - \expandafter\ifx\csname SET#1\endcsname\relax - {[No value for ``#1'']}% - \message{Variable `#1', used in @value, is not set.}% - \else - \csname SET#1\endcsname - \fi -} - -% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined -% with @set. -% -% To get special treatment of `@end ifset,' call \makeond and the redefine. -% -\makecond{ifset} -\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} -\def\doifset#1#2{% - {% - \makevalueexpandable - \let\next=\empty - \expandafter\ifx\csname SET#2\endcsname\relax - #1% If not set, redefine \next. - \fi - \expandafter - }\next -} -\def\ifsetfail{\doignore{ifset}} - -% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been -% defined with @set, or has been undefined with @clear. -% -% The `\else' inside the `\doifset' parameter is a trick to reuse the -% above code: if the variable is not set, do nothing, if it is set, -% then redefine \next to \ifclearfail. -% -\makecond{ifclear} -\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} -\def\ifclearfail{\doignore{ifclear}} - -% @dircategory CATEGORY -- specify a category of the dir file -% which this file should belong to. Ignore this in TeX. -\let\dircategory=\comment - -% @defininfoenclose. -\let\definfoenclose=\comment - - -\message{indexing,} -% Index generation facilities - -% Define \newwrite to be identical to plain tex's \newwrite -% except not \outer, so it can be used within macros and \if's. -\edef\newwrite{\makecsname{ptexnewwrite}} - -% \newindex {foo} defines an index named foo. -% It automatically defines \fooindex such that -% \fooindex ...rest of line... puts an entry in the index foo. -% It also defines \fooindfile to be the number of the output channel for -% the file that accumulates this index. The file's extension is foo. -% The name of an index should be no more than 2 characters long -% for the sake of vms. -% -\def\newindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 % Open the file - \fi - \expandafter\xdef\csname#1index\endcsname{% % Define @#1index - \noexpand\doindex{#1}} -} - -% @defindex foo == \newindex{foo} -% -\def\defindex{\parsearg\newindex} - -% Define @defcodeindex, like @defindex except put all entries in @code. -% -\def\defcodeindex{\parsearg\newcodeindex} -% -\def\newcodeindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 - \fi - \expandafter\xdef\csname#1index\endcsname{% - \noexpand\docodeindex{#1}}% -} - - -% @synindex foo bar makes index foo feed into index bar. -% Do this instead of @defindex foo if you don't want it as a separate index. -% -% @syncodeindex foo bar similar, but put all entries made for index foo -% inside @code. -% -\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} -\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} - -% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), -% #3 the target index (bar). -\def\dosynindex#1#2#3{% - % Only do \closeout if we haven't already done it, else we'll end up - % closing the target index. - \expandafter \ifx\csname donesynindex#2\endcsname \undefined - % The \closeout helps reduce unnecessary open files; the limit on the - % Acorn RISC OS is a mere 16 files. - \expandafter\closeout\csname#2indfile\endcsname - \expandafter\let\csname\donesynindex#2\endcsname = 1 - \fi - % redefine \fooindfile: - \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname - \expandafter\let\csname#2indfile\endcsname=\temp - % redefine \fooindex: - \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% -} - -% Define \doindex, the driver for all \fooindex macros. -% Argument #1 is generated by the calling \fooindex macro, -% and it is "foo", the name of the index. - -% \doindex just uses \parsearg; it calls \doind for the actual work. -% This is because \doind is more useful to call from other macros. - -% There is also \dosubind {index}{topic}{subtopic} -% which makes an entry in a two-level index such as the operation index. - -\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} -\def\singleindexer #1{\doind{\indexname}{#1}} - -% like the previous two, but they put @code around the argument. -\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} -\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} - -% Take care of Texinfo commands that can appear in an index entry. -% Since there are some commands we want to expand, and others we don't, -% we have to laboriously prevent expansion for those that we don't. -% -\def\indexdummies{% - \escapechar = `\\ % use backslash in output files. - \def\@{@}% change to @@ when we switch to @ as escape char in index files. - \def\ {\realbackslash\space }% - % - % Need these in case \tex is in effect and \{ is a \delimiter again. - % But can't use \lbracecmd and \rbracecmd because texindex assumes - % braces and backslashes are used only as delimiters. - \let\{ = \mylbrace - \let\} = \myrbrace - % - % I don't entirely understand this, but when an index entry is - % generated from a macro call, the \endinput which \scanmacro inserts - % causes processing to be prematurely terminated. This is, - % apparently, because \indexsorttmp is fully expanded, and \endinput - % is an expandable command. The redefinition below makes \endinput - % disappear altogether for that purpose -- although logging shows that - % processing continues to some further point. On the other hand, it - % seems \endinput does not hurt in the printed index arg, since that - % is still getting written without apparent harm. - % - % Sample source (mac-idx3.tex, reported by Graham Percival to - % help-texinfo, 22may06): - % @macro funindex {WORD} - % @findex xyz - % @end macro - % ... - % @funindex commtest - % - % The above is not enough to reproduce the bug, but it gives the flavor. - % - % Sample whatsit resulting: - % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} - % - % So: - \let\endinput = \empty - % - % Do the redefinitions. - \commondummies -} - -% For the aux and toc files, @ is the escape character. So we want to -% redefine everything using @ as the escape character (instead of -% \realbackslash, still used for index files). When everything uses @, -% this will be simpler. -% -\def\atdummies{% - \def\@{@@}% - \def\ {@ }% - \let\{ = \lbraceatcmd - \let\} = \rbraceatcmd - % - % Do the redefinitions. - \commondummies - \otherbackslash -} - -% Called from \indexdummies and \atdummies. -% -\def\commondummies{% - % - % \definedummyword defines \#1 as \string\#1\space, thus effectively - % preventing its expansion. This is used only for control% words, - % not control letters, because the \space would be incorrect for - % control characters, but is needed to separate the control word - % from whatever follows. - % - % For control letters, we have \definedummyletter, which omits the - % space. - % - % These can be used both for control words that take an argument and - % those that do not. If it is followed by {arg} in the input, then - % that will dutifully get written to the index (or wherever). - % - \def\definedummyword ##1{\def##1{\string##1\space}}% - \def\definedummyletter##1{\def##1{\string##1}}% - \let\definedummyaccent\definedummyletter - % - \commondummiesnofonts - % - \definedummyletter\_% - % - % Non-English letters. - \definedummyword\AA - \definedummyword\AE - \definedummyword\L - \definedummyword\OE - \definedummyword\O - \definedummyword\aa - \definedummyword\ae - \definedummyword\l - \definedummyword\oe - \definedummyword\o - \definedummyword\ss - \definedummyword\exclamdown - \definedummyword\questiondown - \definedummyword\ordf - \definedummyword\ordm - % - % Although these internal commands shouldn't show up, sometimes they do. - \definedummyword\bf - \definedummyword\gtr - \definedummyword\hat - \definedummyword\less - \definedummyword\sf - \definedummyword\sl - \definedummyword\tclose - \definedummyword\tt - % - \definedummyword\LaTeX - \definedummyword\TeX - % - % Assorted special characters. - \definedummyword\bullet - \definedummyword\comma - \definedummyword\copyright - \definedummyword\registeredsymbol - \definedummyword\dots - \definedummyword\enddots - \definedummyword\equiv - \definedummyword\error - \definedummyword\euro - \definedummyword\expansion - \definedummyword\minus - \definedummyword\pounds - \definedummyword\point - \definedummyword\print - \definedummyword\result - \definedummyword\textdegree - % - % We want to disable all macros so that they are not expanded by \write. - \macrolist - % - \normalturnoffactive - % - % Handle some cases of @value -- where it does not contain any - % (non-fully-expandable) commands. - \makevalueexpandable -} - -% \commondummiesnofonts: common to \commondummies and \indexnofonts. -% -\def\commondummiesnofonts{% - % Control letters and accents. - \definedummyletter\!% - \definedummyaccent\"% - \definedummyaccent\'% - \definedummyletter\*% - \definedummyaccent\,% - \definedummyletter\.% - \definedummyletter\/% - \definedummyletter\:% - \definedummyaccent\=% - \definedummyletter\?% - \definedummyaccent\^% - \definedummyaccent\`% - \definedummyaccent\~% - \definedummyword\u - \definedummyword\v - \definedummyword\H - \definedummyword\dotaccent - \definedummyword\ringaccent - \definedummyword\tieaccent - \definedummyword\ubaraccent - \definedummyword\udotaccent - \definedummyword\dotless - % - % Texinfo font commands. - \definedummyword\b - \definedummyword\i - \definedummyword\r - \definedummyword\sc - \definedummyword\t - % - % Commands that take arguments. - \definedummyword\acronym - \definedummyword\cite - \definedummyword\code - \definedummyword\command - \definedummyword\dfn - \definedummyword\emph - \definedummyword\env - \definedummyword\file - \definedummyword\kbd - \definedummyword\key - \definedummyword\math - \definedummyword\option - \definedummyword\pxref - \definedummyword\ref - \definedummyword\samp - \definedummyword\strong - \definedummyword\tie - \definedummyword\uref - \definedummyword\url - \definedummyword\var - \definedummyword\verb - \definedummyword\w - \definedummyword\xref -} - -% \indexnofonts is used when outputting the strings to sort the index -% by, and when constructing control sequence names. It eliminates all -% control sequences and just writes whatever the best ASCII sort string -% would be for a given command (usually its argument). -% -\def\indexnofonts{% - % Accent commands should become @asis. - \def\definedummyaccent##1{\let##1\asis}% - % We can just ignore other control letters. - \def\definedummyletter##1{\let##1\empty}% - % Hopefully, all control words can become @asis. - \let\definedummyword\definedummyaccent - % - \commondummiesnofonts - % - % Don't no-op \tt, since it isn't a user-level command - % and is used in the definitions of the active chars like <, >, |, etc. - % Likewise with the other plain tex font commands. - %\let\tt=\asis - % - \def\ { }% - \def\@{@}% - % how to handle braces? - \def\_{\normalunderscore}% - % - % Non-English letters. - \def\AA{AA}% - \def\AE{AE}% - \def\L{L}% - \def\OE{OE}% - \def\O{O}% - \def\aa{aa}% - \def\ae{ae}% - \def\l{l}% - \def\oe{oe}% - \def\o{o}% - \def\ss{ss}% - \def\exclamdown{!}% - \def\questiondown{?}% - \def\ordf{a}% - \def\ordm{o}% - % - \def\LaTeX{LaTeX}% - \def\TeX{TeX}% - % - % Assorted special characters. - % (The following {} will end up in the sort string, but that's ok.) - \def\bullet{bullet}% - \def\comma{,}% - \def\copyright{copyright}% - \def\registeredsymbol{R}% - \def\dots{...}% - \def\enddots{...}% - \def\equiv{==}% - \def\error{error}% - \def\euro{euro}% - \def\expansion{==>}% - \def\minus{-}% - \def\pounds{pounds}% - \def\point{.}% - \def\print{-|}% - \def\result{=>}% - \def\textdegree{degrees}% - % - % We need to get rid of all macros, leaving only the arguments (if present). - % Of course this is not nearly correct, but it is the best we can do for now. - % makeinfo does not expand macros in the argument to @deffn, which ends up - % writing an index entry, and texindex isn't prepared for an index sort entry - % that starts with \. - % - % Since macro invocations are followed by braces, we can just redefine them - % to take a single TeX argument. The case of a macro invocation that - % goes to end-of-line is not handled. - % - \macrolist -} - -\let\indexbackslash=0 %overridden during \printindex. -\let\SETmarginindex=\relax % put index entries in margin (undocumented)? - -% Most index entries go through here, but \dosubind is the general case. -% #1 is the index name, #2 is the entry text. -\def\doind#1#2{\dosubind{#1}{#2}{}} - -% Workhorse for all \fooindexes. -% #1 is name of index, #2 is stuff to put there, #3 is subentry -- -% empty if called from \doind, as we usually are (the main exception -% is with most defuns, which call us directly). -% -\def\dosubind#1#2#3{% - \iflinks - {% - % Store the main index entry text (including the third arg). - \toks0 = {#2}% - % If third arg is present, precede it with a space. - \def\thirdarg{#3}% - \ifx\thirdarg\empty \else - \toks0 = \expandafter{\the\toks0 \space #3}% - \fi - % - \edef\writeto{\csname#1indfile\endcsname}% - % - \ifvmode - \dosubindsanitize - \else - \dosubindwrite - \fi - }% - \fi -} - -% Write the entry in \toks0 to the index file: -% -\def\dosubindwrite{% - % Put the index entry in the margin if desired. - \ifx\SETmarginindex\relax\else - \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% - \fi - % - % Remember, we are within a group. - \indexdummies % Must do this here, since \bf, etc expand at this stage - \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now - % so it will be output as is; and it will print as backslash. - % - % Process the index entry with all font commands turned off, to - % get the string to sort by. - {\indexnofonts - \edef\temp{\the\toks0}% need full expansion - \xdef\indexsorttmp{\temp}% - }% - % - % Set up the complete index entry, with both the sort key and - % the original text, including any font commands. We write - % three arguments to \entry to the .?? file (four in the - % subentry case), texindex reduces to two when writing the .??s - % sorted result. - \edef\temp{% - \write\writeto{% - \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% - }% - \temp -} - -% Take care of unwanted page breaks: -% -% If a skip is the last thing on the list now, preserve it -% by backing up by \lastskip, doing the \write, then inserting -% the skip again. Otherwise, the whatsit generated by the -% \write will make \lastskip zero. The result is that sequences -% like this: -% @end defun -% @tindex whatever -% @defun ... -% will have extra space inserted, because the \medbreak in the -% start of the @defun won't see the skip inserted by the @end of -% the previous defun. -% -% But don't do any of this if we're not in vertical mode. We -% don't want to do a \vskip and prematurely end a paragraph. -% -% Avoid page breaks due to these extra skips, too. -% -% But wait, there is a catch there: -% We'll have to check whether \lastskip is zero skip. \ifdim is not -% sufficient for this purpose, as it ignores stretch and shrink parts -% of the skip. The only way seems to be to check the textual -% representation of the skip. -% -% The following is almost like \def\zeroskipmacro{0.0pt} except that -% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). -% -\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} -% -% ..., ready, GO: -% -\def\dosubindsanitize{% - % \lastskip and \lastpenalty cannot both be nonzero simultaneously. - \skip0 = \lastskip - \edef\lastskipmacro{\the\lastskip}% - \count255 = \lastpenalty - % - % If \lastskip is nonzero, that means the last item was a - % skip. And since a skip is discardable, that means this - % -\skip0 glue we're inserting is preceded by a - % non-discardable item, therefore it is not a potential - % breakpoint, therefore no \nobreak needed. - \ifx\lastskipmacro\zeroskipmacro - \else - \vskip-\skip0 - \fi - % - \dosubindwrite - % - \ifx\lastskipmacro\zeroskipmacro - % If \lastskip was zero, perhaps the last item was a penalty, and - % perhaps it was >=10000, e.g., a \nobreak. In that case, we want - % to re-insert the same penalty (values >10000 are used for various - % signals); since we just inserted a non-discardable item, any - % following glue (such as a \parskip) would be a breakpoint. For example: - % - % @deffn deffn-whatever - % @vindex index-whatever - % Description. - % would allow a break between the index-whatever whatsit - % and the "Description." paragraph. - \ifnum\count255>9999 \penalty\count255 \fi - \else - % On the other hand, if we had a nonzero \lastskip, - % this make-up glue would be preceded by a non-discardable item - % (the whatsit from the \write), so we must insert a \nobreak. - \nobreak\vskip\skip0 - \fi -} - -% The index entry written in the file actually looks like -% \entry {sortstring}{page}{topic} -% or -% \entry {sortstring}{page}{topic}{subtopic} -% The texindex program reads in these files and writes files -% containing these kinds of lines: -% \initial {c} -% before the first topic whose initial is c -% \entry {topic}{pagelist} -% for a topic that is used without subtopics -% \primary {topic} -% for the beginning of a topic that is used with subtopics -% \secondary {subtopic}{pagelist} -% for each subtopic. - -% Define the user-accessible indexing commands -% @findex, @vindex, @kindex, @cindex. - -\def\findex {\fnindex} -\def\kindex {\kyindex} -\def\cindex {\cpindex} -\def\vindex {\vrindex} -\def\tindex {\tpindex} -\def\pindex {\pgindex} - -\def\cindexsub {\begingroup\obeylines\cindexsub} -{\obeylines % -\gdef\cindexsub "#1" #2^^M{\endgroup % -\dosubind{cp}{#2}{#1}}} - -% Define the macros used in formatting output of the sorted index material. - -% @printindex causes a particular index (the ??s file) to get printed. -% It does not print any chapter heading (usually an @unnumbered). -% -\parseargdef\printindex{\begingroup - \dobreak \chapheadingskip{10000}% - % - \smallfonts \rm - \tolerance = 9500 - \everypar = {}% don't want the \kern\-parindent from indentation suppression. - % - % See if the index file exists and is nonempty. - % Change catcode of @ here so that if the index file contains - % \initial {@} - % as its first line, TeX doesn't complain about mismatched braces - % (because it thinks @} is a control sequence). - \catcode`\@ = 11 - \openin 1 \jobname.#1s - \ifeof 1 - % \enddoublecolumns gets confused if there is no text in the index, - % and it loses the chapter title and the aux file entries for the - % index. The easiest way to prevent this problem is to make sure - % there is some text. - \putwordIndexNonexistent - \else - % - % If the index file exists but is empty, then \openin leaves \ifeof - % false. We have to make TeX try to read something from the file, so - % it can discover if there is anything in it. - \read 1 to \temp - \ifeof 1 - \putwordIndexIsEmpty - \else - % Index files are almost Texinfo source, but we use \ as the escape - % character. It would be better to use @, but that's too big a change - % to make right now. - \def\indexbackslash{\backslashcurfont}% - \catcode`\\ = 0 - \escapechar = `\\ - \begindoublecolumns - \input \jobname.#1s - \enddoublecolumns - \fi - \fi - \closein 1 -\endgroup} - -% These macros are used by the sorted index file itself. -% Change them to control the appearance of the index. - -\def\initial#1{{% - % Some minor font changes for the special characters. - \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt - % - % Remove any glue we may have, we'll be inserting our own. - \removelastskip - % - % We like breaks before the index initials, so insert a bonus. - \nobreak - \vskip 0pt plus 3\baselineskip - \penalty 0 - \vskip 0pt plus -3\baselineskip - % - % Typeset the initial. Making this add up to a whole number of - % baselineskips increases the chance of the dots lining up from column - % to column. It still won't often be perfect, because of the stretch - % we need before each entry, but it's better. - % - % No shrink because it confuses \balancecolumns. - \vskip 1.67\baselineskip plus .5\baselineskip - \leftline{\secbf #1}% - % Do our best not to break after the initial. - \nobreak - \vskip .33\baselineskip plus .1\baselineskip -}} - -% \entry typesets a paragraph consisting of the text (#1), dot leaders, and -% then page number (#2) flushed to the right margin. It is used for index -% and table of contents entries. The paragraph is indented by \leftskip. -% -% A straightforward implementation would start like this: -% \def\entry#1#2{... -% But this frozes the catcodes in the argument, and can cause problems to -% @code, which sets - active. This problem was fixed by a kludge--- -% ``-'' was active throughout whole index, but this isn't really right. -% -% The right solution is to prevent \entry from swallowing the whole text. -% --kasal, 21nov03 -\def\entry{% - \begingroup - % - % Start a new paragraph if necessary, so our assignments below can't - % affect previous text. - \par - % - % Do not fill out the last line with white space. - \parfillskip = 0in - % - % No extra space above this paragraph. - \parskip = 0in - % - % Do not prefer a separate line ending with a hyphen to fewer lines. - \finalhyphendemerits = 0 - % - % \hangindent is only relevant when the entry text and page number - % don't both fit on one line. In that case, bob suggests starting the - % dots pretty far over on the line. Unfortunately, a large - % indentation looks wrong when the entry text itself is broken across - % lines. So we use a small indentation and put up with long leaders. - % - % \hangafter is reset to 1 (which is the value we want) at the start - % of each paragraph, so we need not do anything with that. - \hangindent = 2em - % - % When the entry text needs to be broken, just fill out the first line - % with blank space. - \rightskip = 0pt plus1fil - % - % A bit of stretch before each entry for the benefit of balancing - % columns. - \vskip 0pt plus1pt - % - % Swallow the left brace of the text (first parameter): - \afterassignment\doentry - \let\temp = -} -\def\doentry{% - \bgroup % Instead of the swallowed brace. - \noindent - \aftergroup\finishentry - % And now comes the text of the entry. -} -\def\finishentry#1{% - % #1 is the page number. - % - % The following is kludged to not output a line of dots in the index if - % there are no page numbers. The next person who breaks this will be - % cursed by a Unix daemon. - \def\tempa{{\rm }}% - \def\tempb{#1}% - \edef\tempc{\tempa}% - \edef\tempd{\tempb}% - \ifx\tempc\tempd - \ % - \else - % - % If we must, put the page number on a line of its own, and fill out - % this line with blank space. (The \hfil is overwhelmed with the - % fill leaders glue in \indexdotfill if the page number does fit.) - \hfil\penalty50 - \null\nobreak\indexdotfill % Have leaders before the page number. - % - % The `\ ' here is removed by the implicit \unskip that TeX does as - % part of (the primitive) \par. Without it, a spurious underfull - % \hbox ensues. - \ifpdf - \pdfgettoks#1.% - \ \the\toksA - \else - \ #1% - \fi - \fi - \par - \endgroup -} - -% Like plain.tex's \dotfill, except uses up at least 1 em. -\def\indexdotfill{\cleaders - \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} - -\def\primary #1{\line{#1\hfil}} - -\newskip\secondaryindent \secondaryindent=0.5cm -\def\secondary#1#2{{% - \parfillskip=0in - \parskip=0in - \hangindent=1in - \hangafter=1 - \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill - \ifpdf - \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. - \else - #2 - \fi - \par -}} - -% Define two-column mode, which we use to typeset indexes. -% Adapted from the TeXbook, page 416, which is to say, -% the manmac.tex format used to print the TeXbook itself. -\catcode`\@=11 - -\newbox\partialpage -\newdimen\doublecolumnhsize - -\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns - % Grab any single-column material above us. - \output = {% - % - % Here is a possibility not foreseen in manmac: if we accumulate a - % whole lot of material, we might end up calling this \output - % routine twice in a row (see the doublecol-lose test, which is - % essentially a couple of indexes with @setchapternewpage off). In - % that case we just ship out what is in \partialpage with the normal - % output routine. Generally, \partialpage will be empty when this - % runs and this will be a no-op. See the indexspread.tex test case. - \ifvoid\partialpage \else - \onepageout{\pagecontents\partialpage}% - \fi - % - \global\setbox\partialpage = \vbox{% - % Unvbox the main output page. - \unvbox\PAGE - \kern-\topskip \kern\baselineskip - }% - }% - \eject % run that output routine to set \partialpage - % - % Use the double-column output routine for subsequent pages. - \output = {\doublecolumnout}% - % - % Change the page size parameters. We could do this once outside this - % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 - % format, but then we repeat the same computation. Repeating a couple - % of assignments once per index is clearly meaningless for the - % execution time, so we may as well do it in one place. - % - % First we halve the line length, less a little for the gutter between - % the columns. We compute the gutter based on the line length, so it - % changes automatically with the paper format. The magic constant - % below is chosen so that the gutter has the same value (well, +-<1pt) - % as it did when we hard-coded it. - % - % We put the result in a separate register, \doublecolumhsize, so we - % can restore it in \pagesofar, after \hsize itself has (potentially) - % been clobbered. - % - \doublecolumnhsize = \hsize - \advance\doublecolumnhsize by -.04154\hsize - \divide\doublecolumnhsize by 2 - \hsize = \doublecolumnhsize - % - % Double the \vsize as well. (We don't need a separate register here, - % since nobody clobbers \vsize.) - \vsize = 2\vsize -} - -% The double-column output routine for all double-column pages except -% the last. -% -\def\doublecolumnout{% - \splittopskip=\topskip \splitmaxdepth=\maxdepth - % Get the available space for the double columns -- the normal - % (undoubled) page height minus any material left over from the - % previous page. - \dimen@ = \vsize - \divide\dimen@ by 2 - \advance\dimen@ by -\ht\partialpage - % - % box0 will be the left-hand column, box2 the right. - \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ - \onepageout\pagesofar - \unvbox255 - \penalty\outputpenalty -} -% -% Re-output the contents of the output page -- any previous material, -% followed by the two boxes we just split, in box0 and box2. -\def\pagesofar{% - \unvbox\partialpage - % - \hsize = \doublecolumnhsize - \wd0=\hsize \wd2=\hsize - \hbox to\pagewidth{\box0\hfil\box2}% -} -% -% All done with double columns. -\def\enddoublecolumns{% - \output = {% - % Split the last of the double-column material. Leave it on the - % current page, no automatic page break. - \balancecolumns - % - % If we end up splitting too much material for the current page, - % though, there will be another page break right after this \output - % invocation ends. Having called \balancecolumns once, we do not - % want to call it again. Therefore, reset \output to its normal - % definition right away. (We hope \balancecolumns will never be - % called on to balance too much material, but if it is, this makes - % the output somewhat more palatable.) - \global\output = {\onepageout{\pagecontents\PAGE}}% - }% - \eject - \endgroup % started in \begindoublecolumns - % - % \pagegoal was set to the doubled \vsize above, since we restarted - % the current page. We're now back to normal single-column - % typesetting, so reset \pagegoal to the normal \vsize (after the - % \endgroup where \vsize got restored). - \pagegoal = \vsize -} -% -% Called at the end of the double column material. -\def\balancecolumns{% - \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. - \dimen@ = \ht0 - \advance\dimen@ by \topskip - \advance\dimen@ by-\baselineskip - \divide\dimen@ by 2 % target to split to - %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% - \splittopskip = \topskip - % Loop until we get a decent breakpoint. - {% - \vbadness = 10000 - \loop - \global\setbox3 = \copy0 - \global\setbox1 = \vsplit3 to \dimen@ - \ifdim\ht3>\dimen@ - \global\advance\dimen@ by 1pt - \repeat - }% - %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% - \setbox0=\vbox to\dimen@{\unvbox1}% - \setbox2=\vbox to\dimen@{\unvbox3}% - % - \pagesofar -} -\catcode`\@ = \other - - -\message{sectioning,} -% Chapters, sections, etc. - -% \unnumberedno is an oxymoron, of course. But we count the unnumbered -% sections so that we can refer to them unambiguously in the pdf -% outlines by their "section number". We avoid collisions with chapter -% numbers by starting them at 10000. (If a document ever has 10000 -% chapters, we're in trouble anyway, I'm sure.) -\newcount\unnumberedno \unnumberedno = 10000 -\newcount\chapno -\newcount\secno \secno=0 -\newcount\subsecno \subsecno=0 -\newcount\subsubsecno \subsubsecno=0 - -% This counter is funny since it counts through charcodes of letters A, B, ... -\newcount\appendixno \appendixno = `\@ -% -% \def\appendixletter{\char\the\appendixno} -% We do the following ugly conditional instead of the above simple -% construct for the sake of pdftex, which needs the actual -% letter in the expansion, not just typeset. -% -\def\appendixletter{% - \ifnum\appendixno=`A A% - \else\ifnum\appendixno=`B B% - \else\ifnum\appendixno=`C C% - \else\ifnum\appendixno=`D D% - \else\ifnum\appendixno=`E E% - \else\ifnum\appendixno=`F F% - \else\ifnum\appendixno=`G G% - \else\ifnum\appendixno=`H H% - \else\ifnum\appendixno=`I I% - \else\ifnum\appendixno=`J J% - \else\ifnum\appendixno=`K K% - \else\ifnum\appendixno=`L L% - \else\ifnum\appendixno=`M M% - \else\ifnum\appendixno=`N N% - \else\ifnum\appendixno=`O O% - \else\ifnum\appendixno=`P P% - \else\ifnum\appendixno=`Q Q% - \else\ifnum\appendixno=`R R% - \else\ifnum\appendixno=`S S% - \else\ifnum\appendixno=`T T% - \else\ifnum\appendixno=`U U% - \else\ifnum\appendixno=`V V% - \else\ifnum\appendixno=`W W% - \else\ifnum\appendixno=`X X% - \else\ifnum\appendixno=`Y Y% - \else\ifnum\appendixno=`Z Z% - % The \the is necessary, despite appearances, because \appendixletter is - % expanded while writing the .toc file. \char\appendixno is not - % expandable, thus it is written literally, thus all appendixes come out - % with the same letter (or @) in the toc without it. - \else\char\the\appendixno - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} - -% Each @chapter defines this as the name of the chapter. -% page headings and footings can use it. @section does likewise. -% However, they are not reliable, because we don't use marks. -\def\thischapter{} -\def\thissection{} - -\newcount\absseclevel % used to calculate proper heading level -\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count - -% @raisesections: treat @section as chapter, @subsection as section, etc. -\def\raisesections{\global\advance\secbase by -1} -\let\up=\raisesections % original BFox name - -% @lowersections: treat @chapter as section, @section as subsection, etc. -\def\lowersections{\global\advance\secbase by 1} -\let\down=\lowersections % original BFox name - -% we only have subsub. -\chardef\maxseclevel = 3 -% -% A numbered section within an unnumbered changes to unnumbered too. -% To achive this, remember the "biggest" unnum. sec. we are currently in: -\chardef\unmlevel = \maxseclevel -% -% Trace whether the current chapter is an appendix or not: -% \chapheadtype is "N" or "A", unnumbered chapters are ignored. -\def\chapheadtype{N} - -% Choose a heading macro -% #1 is heading type -% #2 is heading level -% #3 is text for heading -\def\genhead#1#2#3{% - % Compute the abs. sec. level: - \absseclevel=#2 - \advance\absseclevel by \secbase - % Make sure \absseclevel doesn't fall outside the range: - \ifnum \absseclevel < 0 - \absseclevel = 0 - \else - \ifnum \absseclevel > 3 - \absseclevel = 3 - \fi - \fi - % The heading type: - \def\headtype{#1}% - \if \headtype U% - \ifnum \absseclevel < \unmlevel - \chardef\unmlevel = \absseclevel - \fi - \else - % Check for appendix sections: - \ifnum \absseclevel = 0 - \edef\chapheadtype{\headtype}% - \else - \if \headtype A\if \chapheadtype N% - \errmessage{@appendix... within a non-appendix chapter}% - \fi\fi - \fi - % Check for numbered within unnumbered: - \ifnum \absseclevel > \unmlevel - \def\headtype{U}% - \else - \chardef\unmlevel = 3 - \fi - \fi - % Now print the heading: - \if \headtype U% - \ifcase\absseclevel - \unnumberedzzz{#3}% - \or \unnumberedseczzz{#3}% - \or \unnumberedsubseczzz{#3}% - \or \unnumberedsubsubseczzz{#3}% - \fi - \else - \if \headtype A% - \ifcase\absseclevel - \appendixzzz{#3}% - \or \appendixsectionzzz{#3}% - \or \appendixsubseczzz{#3}% - \or \appendixsubsubseczzz{#3}% - \fi - \else - \ifcase\absseclevel - \chapterzzz{#3}% - \or \seczzz{#3}% - \or \numberedsubseczzz{#3}% - \or \numberedsubsubseczzz{#3}% - \fi - \fi - \fi - \suppressfirstparagraphindent -} - -% an interface: -\def\numhead{\genhead N} -\def\apphead{\genhead A} -\def\unnmhead{\genhead U} - -% @chapter, @appendix, @unnumbered. Increment top-level counter, reset -% all lower-level sectioning counters to zero. -% -% Also set \chaplevelprefix, which we prepend to @float sequence numbers -% (e.g., figures), q.v. By default (before any chapter), that is empty. -\let\chaplevelprefix = \empty -% -\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz -\def\chapterzzz#1{% - % section resetting is \global in case the chapter is in a group, such - % as an @include file. - \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 - \global\advance\chapno by 1 - % - % Used for \float. - \gdef\chaplevelprefix{\the\chapno.}% - \resetallfloatnos - % - \message{\putwordChapter\space \the\chapno}% - % - % Write the actual heading. - \chapmacro{#1}{Ynumbered}{\the\chapno}% - % - % So @section and the like are numbered underneath this chapter. - \global\let\section = \numberedsec - \global\let\subsection = \numberedsubsec - \global\let\subsubsection = \numberedsubsubsec -} - -\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz -\def\appendixzzz#1{% - \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 - \global\advance\appendixno by 1 - \gdef\chaplevelprefix{\appendixletter.}% - \resetallfloatnos - % - \def\appendixnum{\putwordAppendix\space \appendixletter}% - \message{\appendixnum}% - % - \chapmacro{#1}{Yappendix}{\appendixletter}% - % - \global\let\section = \appendixsec - \global\let\subsection = \appendixsubsec - \global\let\subsubsection = \appendixsubsubsec -} - -\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz -\def\unnumberedzzz#1{% - \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 - \global\advance\unnumberedno by 1 - % - % Since an unnumbered has no number, no prefix for figures. - \global\let\chaplevelprefix = \empty - \resetallfloatnos - % - % This used to be simply \message{#1}, but TeX fully expands the - % argument to \message. Therefore, if #1 contained @-commands, TeX - % expanded them. For example, in `@unnumbered The @cite{Book}', TeX - % expanded @cite (which turns out to cause errors because \cite is meant - % to be executed, not expanded). - % - % Anyway, we don't want the fully-expanded definition of @cite to appear - % as a result of the \message, we just want `@cite' itself. We use - % \the to achieve this: TeX expands \the only once, - % simply yielding the contents of . (We also do this for - % the toc entries.) - \toks0 = {#1}% - \message{(\the\toks0)}% - % - \chapmacro{#1}{Ynothing}{\the\unnumberedno}% - % - \global\let\section = \unnumberedsec - \global\let\subsection = \unnumberedsubsec - \global\let\subsubsection = \unnumberedsubsubsec -} - -% @centerchap is like @unnumbered, but the heading is centered. -\outer\parseargdef\centerchap{% - % Well, we could do the following in a group, but that would break - % an assumption that \chapmacro is called at the outermost level. - % Thus we are safer this way: --kasal, 24feb04 - \let\centerparametersmaybe = \centerparameters - \unnmhead0{#1}% - \let\centerparametersmaybe = \relax -} - -% @top is like @unnumbered. -\let\top\unnumbered - -% Sections. -\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz -\def\seczzz#1{% - \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 - \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% -} - -\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz -\def\appendixsectionzzz#1{% - \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 - \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% -} -\let\appendixsec\appendixsection - -\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz -\def\unnumberedseczzz#1{% - \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 - \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% -} - -% Subsections. -\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz -\def\numberedsubseczzz#1{% - \global\subsubsecno=0 \global\advance\subsecno by 1 - \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% -} - -\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz -\def\appendixsubseczzz#1{% - \global\subsubsecno=0 \global\advance\subsecno by 1 - \sectionheading{#1}{subsec}{Yappendix}% - {\appendixletter.\the\secno.\the\subsecno}% -} - -\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz -\def\unnumberedsubseczzz#1{% - \global\subsubsecno=0 \global\advance\subsecno by 1 - \sectionheading{#1}{subsec}{Ynothing}% - {\the\unnumberedno.\the\secno.\the\subsecno}% -} - -% Subsubsections. -\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz -\def\numberedsubsubseczzz#1{% - \global\advance\subsubsecno by 1 - \sectionheading{#1}{subsubsec}{Ynumbered}% - {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% -} - -\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz -\def\appendixsubsubseczzz#1{% - \global\advance\subsubsecno by 1 - \sectionheading{#1}{subsubsec}{Yappendix}% - {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% -} - -\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz -\def\unnumberedsubsubseczzz#1{% - \global\advance\subsubsecno by 1 - \sectionheading{#1}{subsubsec}{Ynothing}% - {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% -} - -% These macros control what the section commands do, according -% to what kind of chapter we are in (ordinary, appendix, or unnumbered). -% Define them by default for a numbered chapter. -\let\section = \numberedsec -\let\subsection = \numberedsubsec -\let\subsubsection = \numberedsubsubsec - -% Define @majorheading, @heading and @subheading - -% NOTE on use of \vbox for chapter headings, section headings, and such: -% 1) We use \vbox rather than the earlier \line to permit -% overlong headings to fold. -% 2) \hyphenpenalty is set to 10000 because hyphenation in a -% heading is obnoxious; this forbids it. -% 3) Likewise, headings look best if no \parindent is used, and -% if justification is not attempted. Hence \raggedright. - - -\def\majorheading{% - {\advance\chapheadingskip by 10pt \chapbreak }% - \parsearg\chapheadingzzz -} - -\def\chapheading{\chapbreak \parsearg\chapheadingzzz} -\def\chapheadingzzz#1{% - {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}% - \bigskip \par\penalty 200\relax - \suppressfirstparagraphindent -} - -% @heading, @subheading, @subsubheading. -\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} - \suppressfirstparagraphindent} -\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} - \suppressfirstparagraphindent} -\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} - \suppressfirstparagraphindent} - -% These macros generate a chapter, section, etc. heading only -% (including whitespace, linebreaking, etc. around it), -% given all the information in convenient, parsed form. - -%%% Args are the skip and penalty (usually negative) -\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} - -%%% Define plain chapter starts, and page on/off switching for it -% Parameter controlling skip before chapter headings (if needed) - -\newskip\chapheadingskip - -\def\chapbreak{\dobreak \chapheadingskip {-4000}} -\def\chappager{\par\vfill\supereject} -\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} - -\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} - -\def\CHAPPAGoff{% -\global\let\contentsalignmacro = \chappager -\global\let\pchapsepmacro=\chapbreak -\global\let\pagealignmacro=\chappager} - -\def\CHAPPAGon{% -\global\let\contentsalignmacro = \chappager -\global\let\pchapsepmacro=\chappager -\global\let\pagealignmacro=\chappager -\global\def\HEADINGSon{\HEADINGSsingle}} - -\def\CHAPPAGodd{% -\global\let\contentsalignmacro = \chapoddpage -\global\let\pchapsepmacro=\chapoddpage -\global\let\pagealignmacro=\chapoddpage -\global\def\HEADINGSon{\HEADINGSdouble}} - -\CHAPPAGon - -% Chapter opening. -% -% #1 is the text, #2 is the section type (Ynumbered, Ynothing, -% Yappendix, Yomitfromtoc), #3 the chapter number. -% -% To test against our argument. -\def\Ynothingkeyword{Ynothing} -\def\Yomitfromtockeyword{Yomitfromtoc} -\def\Yappendixkeyword{Yappendix} -% -\def\chapmacro#1#2#3{% - \pchapsepmacro - {% - \chapfonts \rm - % - % Have to define \thissection before calling \donoderef, because the - % xref code eventually uses it. On the other hand, it has to be called - % after \pchapsepmacro, or the headline will change too soon. - \gdef\thissection{#1}% - \gdef\thischaptername{#1}% - % - % Only insert the separating space if we have a chapter/appendix - % number, and don't print the unnumbered ``number''. - \def\temptype{#2}% - \ifx\temptype\Ynothingkeyword - \setbox0 = \hbox{}% - \def\toctype{unnchap}% - \gdef\thischapternum{}% - \gdef\thischapter{#1}% - \else\ifx\temptype\Yomitfromtockeyword - \setbox0 = \hbox{}% contents like unnumbered, but no toc entry - \def\toctype{omit}% - \gdef\thischapternum{}% - \gdef\thischapter{}% - \else\ifx\temptype\Yappendixkeyword - \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% - \def\toctype{app}% - \xdef\thischapternum{\appendixletter}% - % We don't substitute the actual chapter name into \thischapter - % because we don't want its macros evaluated now. And we don't - % use \thissection because that changes with each section. - % - \xdef\thischapter{\putwordAppendix{} \appendixletter: - \noexpand\thischaptername}% - \else - \setbox0 = \hbox{#3\enspace}% - \def\toctype{numchap}% - \xdef\thischapternum{\the\chapno}% - \xdef\thischapter{\putwordChapter{} \the\chapno: - \noexpand\thischaptername}% - \fi\fi\fi - % - % Write the toc entry for this chapter. Must come before the - % \donoderef, because we include the current node name in the toc - % entry, and \donoderef resets it to empty. - \writetocentry{\toctype}{#1}{#3}% - % - % For pdftex, we have to write out the node definition (aka, make - % the pdfdest) after any page break, but before the actual text has - % been typeset. If the destination for the pdf outline is after the - % text, then jumping from the outline may wind up with the text not - % being visible, for instance under high magnification. - \donoderef{#2}% - % - % Typeset the actual heading. - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent=\wd0 \centerparametersmaybe - \unhbox0 #1\par}% - }% - \nobreak\bigskip % no page break after a chapter title - \nobreak -} - -% @centerchap -- centered and unnumbered. -\let\centerparametersmaybe = \relax -\def\centerparameters{% - \advance\rightskip by 3\rightskip - \leftskip = \rightskip - \parfillskip = 0pt -} - - -% I don't think this chapter style is supported any more, so I'm not -% updating it with the new noderef stuff. We'll see. --karl, 11aug03. -% -\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} -% -\def\unnchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\nobreak -} -\def\chfopen #1#2{\chapoddpage {\chapfonts -\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% -\par\penalty 5000 % -} -\def\centerchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt - \hfill {\rm #1}\hfill}}\bigskip \par\nobreak -} -\def\CHAPFopen{% - \global\let\chapmacro=\chfopen - \global\let\centerchapmacro=\centerchfopen} - - -% Section titles. These macros combine the section number parts and -% call the generic \sectionheading to do the printing. -% -\newskip\secheadingskip -\def\secheadingbreak{\dobreak \secheadingskip{-1000}} - -% Subsection titles. -\newskip\subsecheadingskip -\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} - -% Subsubsection titles. -\def\subsubsecheadingskip{\subsecheadingskip} -\def\subsubsecheadingbreak{\subsecheadingbreak} - - -% Print any size, any type, section title. -% -% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is -% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the -% section number. -% -\def\sectionheading#1#2#3#4{% - {% - % Switch to the right set of fonts. - \csname #2fonts\endcsname \rm - % - % Insert space above the heading. - \csname #2headingbreak\endcsname - % - % Only insert the space after the number if we have a section number. - \def\sectionlevel{#2}% - \def\temptype{#3}% - % - \ifx\temptype\Ynothingkeyword - \setbox0 = \hbox{}% - \def\toctype{unn}% - \gdef\thissection{#1}% - \else\ifx\temptype\Yomitfromtockeyword - % for @headings -- no section number, don't include in toc, - % and don't redefine \thissection. - \setbox0 = \hbox{}% - \def\toctype{omit}% - \let\sectionlevel=\empty - \else\ifx\temptype\Yappendixkeyword - \setbox0 = \hbox{#4\enspace}% - \def\toctype{app}% - \gdef\thissection{#1}% - \else - \setbox0 = \hbox{#4\enspace}% - \def\toctype{num}% - \gdef\thissection{#1}% - \fi\fi\fi - % - % Write the toc entry (before \donoderef). See comments in \chapmacro. - \writetocentry{\toctype\sectionlevel}{#1}{#4}% - % - % Write the node reference (= pdf destination for pdftex). - % Again, see comments in \chapmacro. - \donoderef{#3}% - % - % Interline glue will be inserted when the vbox is completed. - % That glue will be a valid breakpoint for the page, since it'll be - % preceded by a whatsit (usually from the \donoderef, or from the - % \writetocentry if there was no node). We don't want to allow that - % break, since then the whatsits could end up on page n while the - % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. - \nobreak - % - % Output the actual section heading. - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent=\wd0 % zero if no section number - \unhbox0 #1}% - }% - % Add extra space after the heading -- half of whatever came above it. - % Don't allow stretch, though. - \kern .5 \csname #2headingskip\endcsname - % - % Do not let the kern be a potential breakpoint, as it would be if it - % was followed by glue. - \nobreak - % - % We'll almost certainly start a paragraph next, so don't let that - % glue accumulate. (Not a breakpoint because it's preceded by a - % discardable item.) - \vskip-\parskip - % - % This is purely so the last item on the list is a known \penalty > - % 10000. This is so \startdefun can avoid allowing breakpoints after - % section headings. Otherwise, it would insert a valid breakpoint between: - % - % @section sec-whatever - % @deffn def-whatever - \penalty 10001 -} - - -\message{toc,} -% Table of contents. -\newwrite\tocfile - -% Write an entry to the toc file, opening it if necessary. -% Called from @chapter, etc. -% -% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} -% We append the current node name (if any) and page number as additional -% arguments for the \{chap,sec,...}entry macros which will eventually -% read this. The node name is used in the pdf outlines as the -% destination to jump to. -% -% We open the .toc file for writing here instead of at @setfilename (or -% any other fixed time) so that @contents can be anywhere in the document. -% But if #1 is `omit', then we don't do anything. This is used for the -% table of contents chapter openings themselves. -% -\newif\iftocfileopened -\def\omitkeyword{omit}% -% -\def\writetocentry#1#2#3{% - \edef\writetoctype{#1}% - \ifx\writetoctype\omitkeyword \else - \iftocfileopened\else - \immediate\openout\tocfile = \jobname.toc - \global\tocfileopenedtrue - \fi - % - \iflinks - {\atdummies - \edef\temp{% - \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% - \temp - }% - \fi - \fi - % - % Tell \shipout to create a pdf destination on each page, if we're - % writing pdf. These are used in the table of contents. We can't - % just write one on every page because the title pages are numbered - % 1 and 2 (the page numbers aren't printed), and so are the first - % two pages of the document. Thus, we'd have two destinations named - % `1', and two named `2'. - \ifpdf \global\pdfmakepagedesttrue \fi -} - - -% These characters do not print properly in the Computer Modern roman -% fonts, so we must take special care. This is more or less redundant -% with the Texinfo input format setup at the end of this file. -% -\def\activecatcodes{% - \catcode`\"=\active - \catcode`\$=\active - \catcode`\<=\active - \catcode`\>=\active - \catcode`\\=\active - \catcode`\^=\active - \catcode`\_=\active - \catcode`\|=\active - \catcode`\~=\active -} - - -% Read the toc file, which is essentially Texinfo input. -\def\readtocfile{% - \setupdatafile - \activecatcodes - \input \jobname.toc -} - -\newskip\contentsrightmargin \contentsrightmargin=1in -\newcount\savepageno -\newcount\lastnegativepageno \lastnegativepageno = -1 - -% Prepare to read what we've written to \tocfile. -% -\def\startcontents#1{% - % If @setchapternewpage on, and @headings double, the contents should - % start on an odd page, unlike chapters. Thus, we maintain - % \contentsalignmacro in parallel with \pagealignmacro. - % From: Torbjorn Granlund - \contentsalignmacro - \immediate\closeout\tocfile - % - % Don't need to put `Contents' or `Short Contents' in the headline. - % It is abundantly clear what they are. - \def\thischapter{}% - \chapmacro{#1}{Yomitfromtoc}{}% - % - \savepageno = \pageno - \begingroup % Set up to handle contents files properly. - \raggedbottom % Worry more about breakpoints than the bottom. - \advance\hsize by -\contentsrightmargin % Don't use the full line length. - % - % Roman numerals for page numbers. - \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi -} - - -% Normal (long) toc. -\def\contents{% - \startcontents{\putwordTOC}% - \openin 1 \jobname.toc - \ifeof 1 \else - \readtocfile - \fi - \vfill \eject - \contentsalignmacro % in case @setchapternewpage odd is in effect - \ifeof 1 \else - \pdfmakeoutlines - \fi - \closein 1 - \endgroup - \lastnegativepageno = \pageno - \global\pageno = \savepageno -} - -% And just the chapters. -\def\summarycontents{% - \startcontents{\putwordShortTOC}% - % - \let\numchapentry = \shortchapentry - \let\appentry = \shortchapentry - \let\unnchapentry = \shortunnchapentry - % We want a true roman here for the page numbers. - \secfonts - \let\rm=\shortcontrm \let\bf=\shortcontbf - \let\sl=\shortcontsl \let\tt=\shortconttt - \rm - \hyphenpenalty = 10000 - \advance\baselineskip by 1pt % Open it up a little. - \def\numsecentry##1##2##3##4{} - \let\appsecentry = \numsecentry - \let\unnsecentry = \numsecentry - \let\numsubsecentry = \numsecentry - \let\appsubsecentry = \numsecentry - \let\unnsubsecentry = \numsecentry - \let\numsubsubsecentry = \numsecentry - \let\appsubsubsecentry = \numsecentry - \let\unnsubsubsecentry = \numsecentry - \openin 1 \jobname.toc - \ifeof 1 \else - \readtocfile - \fi - \closein 1 - \vfill \eject - \contentsalignmacro % in case @setchapternewpage odd is in effect - \endgroup - \lastnegativepageno = \pageno - \global\pageno = \savepageno -} -\let\shortcontents = \summarycontents - -% Typeset the label for a chapter or appendix for the short contents. -% The arg is, e.g., `A' for an appendix, or `3' for a chapter. -% -\def\shortchaplabel#1{% - % This space should be enough, since a single number is .5em, and the - % widest letter (M) is 1em, at least in the Computer Modern fonts. - % But use \hss just in case. - % (This space doesn't include the extra space that gets added after - % the label; that gets put in by \shortchapentry above.) - % - % We'd like to right-justify chapter numbers, but that looks strange - % with appendix letters. And right-justifying numbers and - % left-justifying letters looks strange when there is less than 10 - % chapters. Have to read the whole toc once to know how many chapters - % there are before deciding ... - \hbox to 1em{#1\hss}% -} - -% These macros generate individual entries in the table of contents. -% The first argument is the chapter or section name. -% The last argument is the page number. -% The arguments in between are the chapter number, section number, ... - -% Chapters, in the main contents. -\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} -% -% Chapters, in the short toc. -% See comments in \dochapentry re vbox and related settings. -\def\shortchapentry#1#2#3#4{% - \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% -} - -% Appendices, in the main contents. -% Need the word Appendix, and a fixed-size box. -% -\def\appendixbox#1{% - % We use M since it's probably the widest letter. - \setbox0 = \hbox{\putwordAppendix{} M}% - \hbox to \wd0{\putwordAppendix{} #1\hss}} -% -\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} - -% Unnumbered chapters. -\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} -\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} - -% Sections. -\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} -\let\appsecentry=\numsecentry -\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} - -% Subsections. -\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} -\let\appsubsecentry=\numsubsecentry -\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} - -% And subsubsections. -\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} -\let\appsubsubsecentry=\numsubsubsecentry -\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} - -% This parameter controls the indentation of the various levels. -% Same as \defaultparindent. -\newdimen\tocindent \tocindent = 15pt - -% Now for the actual typesetting. In all these, #1 is the text and #2 is the -% page number. -% -% If the toc has to be broken over pages, we want it to be at chapters -% if at all possible; hence the \penalty. -\def\dochapentry#1#2{% - \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip - \begingroup - \chapentryfonts - \tocentry{#1}{\dopageno\bgroup#2\egroup}% - \endgroup - \nobreak\vskip .25\baselineskip plus.1\baselineskip -} - -\def\dosecentry#1#2{\begingroup - \secentryfonts \leftskip=\tocindent - \tocentry{#1}{\dopageno\bgroup#2\egroup}% -\endgroup} - -\def\dosubsecentry#1#2{\begingroup - \subsecentryfonts \leftskip=2\tocindent - \tocentry{#1}{\dopageno\bgroup#2\egroup}% -\endgroup} - -\def\dosubsubsecentry#1#2{\begingroup - \subsubsecentryfonts \leftskip=3\tocindent - \tocentry{#1}{\dopageno\bgroup#2\egroup}% -\endgroup} - -% We use the same \entry macro as for the index entries. -\let\tocentry = \entry - -% Space between chapter (or whatever) number and the title. -\def\labelspace{\hskip1em \relax} - -\def\dopageno#1{{\rm #1}} -\def\doshortpageno#1{{\rm #1}} - -\def\chapentryfonts{\secfonts \rm} -\def\secentryfonts{\textfonts} -\def\subsecentryfonts{\textfonts} -\def\subsubsecentryfonts{\textfonts} - - -\message{environments,} -% @foo ... @end foo. - -% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. -% -% Since these characters are used in examples, it should be an even number of -% \tt widths. Each \tt character is 1en, so two makes it 1em. -% -\def\point{$\star$} -\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} -\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} -\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} -\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} - -% The @error{} command. -% Adapted from the TeXbook's \boxit. -% -\newbox\errorbox -% -{\tentt \global\dimen0 = 3em}% Width of the box. -\dimen2 = .55pt % Thickness of rules -% The text. (`r' is open on the right, `e' somewhat less so on the left.) -\setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt} -% -\setbox\errorbox=\hbox to \dimen0{\hfil - \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. - \advance\hsize by -2\dimen2 % Rules. - \vbox{% - \hrule height\dimen2 - \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. - \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. - \kern3pt\vrule width\dimen2}% Space to right. - \hrule height\dimen2} - \hfil} -% -\def\error{\leavevmode\lower.7ex\copy\errorbox} - -% @tex ... @end tex escapes into raw Tex temporarily. -% One exception: @ is still an escape character, so that @end tex works. -% But \@ or @@ will get a plain tex @ character. - -\envdef\tex{% - \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 - \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 - \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie - \catcode `\%=14 - \catcode `\+=\other - \catcode `\"=\other - \catcode `\|=\other - \catcode `\<=\other - \catcode `\>=\other - \escapechar=`\\ - % - \let\b=\ptexb - \let\bullet=\ptexbullet - \let\c=\ptexc - \let\,=\ptexcomma - \let\.=\ptexdot - \let\dots=\ptexdots - \let\equiv=\ptexequiv - \let\!=\ptexexclam - \let\i=\ptexi - \let\indent=\ptexindent - \let\noindent=\ptexnoindent - \let\{=\ptexlbrace - \let\+=\tabalign - \let\}=\ptexrbrace - \let\/=\ptexslash - \let\*=\ptexstar - \let\t=\ptext - \let\frenchspacing=\plainfrenchspacing - % - \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% - \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% - \def\@{@}% -} -% There is no need to define \Etex. - -% Define @lisp ... @end lisp. -% @lisp environment forms a group so it can rebind things, -% including the definition of @end lisp (which normally is erroneous). - -% Amount to narrow the margins by for @lisp. -\newskip\lispnarrowing \lispnarrowing=0.4in - -% This is the definition that ^^M gets inside @lisp, @example, and other -% such environments. \null is better than a space, since it doesn't -% have any width. -\def\lisppar{\null\endgraf} - -% This space is always present above and below environments. -\newskip\envskipamount \envskipamount = 0pt - -% Make spacing and below environment symmetrical. We use \parskip here -% to help in doing that, since in @example-like environments \parskip -% is reset to zero; thus the \afterenvbreak inserts no space -- but the -% start of the next paragraph will insert \parskip. -% -\def\aboveenvbreak{{% - % =10000 instead of <10000 because of a special case in \itemzzz and - % \sectionheading, q.v. - \ifnum \lastpenalty=10000 \else - \advance\envskipamount by \parskip - \endgraf - \ifdim\lastskip<\envskipamount - \removelastskip - % it's not a good place to break if the last penalty was \nobreak - % or better ... - \ifnum\lastpenalty<10000 \penalty-50 \fi - \vskip\envskipamount - \fi - \fi -}} - -\let\afterenvbreak = \aboveenvbreak - -% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will -% also clear it, so that its embedded environments do the narrowing again. -\let\nonarrowing=\relax - -% @cartouche ... @end cartouche: draw rectangle w/rounded corners around -% environment contents. -\font\circle=lcircle10 -\newdimen\circthick -\newdimen\cartouter\newdimen\cartinner -\newskip\normbskip\newskip\normpskip\newskip\normlskip -\circthick=\fontdimen8\circle -% -\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth -\def\ctr{{\hskip 6pt\circle\char'010}} -\def\cbl{{\circle\char'012\hskip -6pt}} -\def\cbr{{\hskip 6pt\circle\char'011}} -\def\carttop{\hbox to \cartouter{\hskip\lskip - \ctl\leaders\hrule height\circthick\hfil\ctr - \hskip\rskip}} -\def\cartbot{\hbox to \cartouter{\hskip\lskip - \cbl\leaders\hrule height\circthick\hfil\cbr - \hskip\rskip}} -% -\newskip\lskip\newskip\rskip - -\envdef\cartouche{% - \ifhmode\par\fi % can't be in the midst of a paragraph. - \startsavinginserts - \lskip=\leftskip \rskip=\rightskip - \leftskip=0pt\rightskip=0pt % we want these *outside*. - \cartinner=\hsize \advance\cartinner by-\lskip - \advance\cartinner by-\rskip - \cartouter=\hsize - \advance\cartouter by 18.4pt % allow for 3pt kerns on either - % side, and for 6pt waste from - % each corner char, and rule thickness - \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip - % Flag to tell @lisp, etc., not to narrow margin. - \let\nonarrowing = t% - \vbox\bgroup - \baselineskip=0pt\parskip=0pt\lineskip=0pt - \carttop - \hbox\bgroup - \hskip\lskip - \vrule\kern3pt - \vbox\bgroup - \kern3pt - \hsize=\cartinner - \baselineskip=\normbskip - \lineskip=\normlskip - \parskip=\normpskip - \vskip -\parskip - \comment % For explanation, see the end of \def\group. -} -\def\Ecartouche{% - \ifhmode\par\fi - \kern3pt - \egroup - \kern3pt\vrule - \hskip\rskip - \egroup - \cartbot - \egroup - \checkinserts -} - - -% This macro is called at the beginning of all the @example variants, -% inside a group. -\def\nonfillstart{% - \aboveenvbreak - \hfuzz = 12pt % Don't be fussy - \sepspaces % Make spaces be word-separators rather than space tokens. - \let\par = \lisppar % don't ignore blank lines - \obeylines % each line of input is a line of output - \parskip = 0pt - \parindent = 0pt - \emergencystretch = 0pt % don't try to avoid overfull boxes - \ifx\nonarrowing\relax - \advance \leftskip by \lispnarrowing - \exdentamount=\lispnarrowing - \else - \let\nonarrowing = \relax - \fi - \let\exdent=\nofillexdent -} - -% If you want all examples etc. small: @set dispenvsize small. -% If you want even small examples the full size: @set dispenvsize nosmall. -% This affects the following displayed environments: -% @example, @display, @format, @lisp -% -\def\smallword{small} -\def\nosmallword{nosmall} -\let\SETdispenvsize\relax -\def\setnormaldispenv{% - \ifx\SETdispenvsize\smallword - \smallexamplefonts \rm - \fi -} -\def\setsmalldispenv{% - \ifx\SETdispenvsize\nosmallword - \else - \smallexamplefonts \rm - \fi -} - -% We often define two environments, @foo and @smallfoo. -% Let's do it by one command: -\def\makedispenv #1#2{ - \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} - \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} - \expandafter\let\csname E#1\endcsname \afterenvbreak - \expandafter\let\csname Esmall#1\endcsname \afterenvbreak -} - -% Define two synonyms: -\def\maketwodispenvs #1#2#3{ - \makedispenv{#1}{#3} - \makedispenv{#2}{#3} -} - -% @lisp: indented, narrowed, typewriter font; @example: same as @lisp. -% -% @smallexample and @smalllisp: use smaller fonts. -% Originally contributed by Pavel@xerox. -% -\maketwodispenvs {lisp}{example}{% - \nonfillstart - \tt\quoteexpand - \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. - \gobble % eat return -} -% @display/@smalldisplay: same as @lisp except keep current font. -% -\makedispenv {display}{% - \nonfillstart - \gobble -} - -% @format/@smallformat: same as @display except don't narrow margins. -% -\makedispenv{format}{% - \let\nonarrowing = t% - \nonfillstart - \gobble -} - -% @flushleft: same as @format, but doesn't obey \SETdispenvsize. -\envdef\flushleft{% - \let\nonarrowing = t% - \nonfillstart - \gobble -} -\let\Eflushleft = \afterenvbreak - -% @flushright. -% -\envdef\flushright{% - \let\nonarrowing = t% - \nonfillstart - \advance\leftskip by 0pt plus 1fill - \gobble -} -\let\Eflushright = \afterenvbreak - - -% @quotation does normal linebreaking (hence we can't use \nonfillstart) -% and narrows the margins. We keep \parskip nonzero in general, since -% we're doing normal filling. So, when using \aboveenvbreak and -% \afterenvbreak, temporarily make \parskip 0. -% -\envdef\quotation{% - {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip - \parindent=0pt - % - % @cartouche defines \nonarrowing to inhibit narrowing at next level down. - \ifx\nonarrowing\relax - \advance\leftskip by \lispnarrowing - \advance\rightskip by \lispnarrowing - \exdentamount = \lispnarrowing - \else - \let\nonarrowing = \relax - \fi - \parsearg\quotationlabel -} - -% We have retained a nonzero parskip for the environment, since we're -% doing normal filling. -% -\def\Equotation{% - \par - \ifx\quotationauthor\undefined\else - % indent a bit. - \leftline{\kern 2\leftskip \sl ---\quotationauthor}% - \fi - {\parskip=0pt \afterenvbreak}% -} - -% If we're given an argument, typeset it in bold with a colon after. -\def\quotationlabel#1{% - \def\temp{#1}% - \ifx\temp\empty \else - {\bf #1: }% - \fi -} - - -% LaTeX-like @verbatim...@end verbatim and @verb{...} -% If we want to allow any as delimiter, -% we need the curly braces so that makeinfo sees the @verb command, eg: -% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org -% -% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. -% -% [Knuth] p.344; only we need to do the other characters Texinfo sets -% active too. Otherwise, they get lost as the first character on a -% verbatim line. -\def\dospecials{% - \do\ \do\\\do\{\do\}\do\$\do\&% - \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% - \do\<\do\>\do\|\do\@\do+\do\"% -} -% -% [Knuth] p. 380 -\def\uncatcodespecials{% - \def\do##1{\catcode`##1=\other}\dospecials} -% -% [Knuth] pp. 380,381,391 -% Disable Spanish ligatures ?` and !` of \tt font -\begingroup - \catcode`\`=\active\gdef`{\relax\lq} -\endgroup -% -% Setup for the @verb command. -% -% Eight spaces for a tab -\begingroup - \catcode`\^^I=\active - \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} -\endgroup -% -\def\setupverb{% - \tt % easiest (and conventionally used) font for verbatim - \def\par{\leavevmode\endgraf}% - \catcode`\`=\active - \tabeightspaces - % Respect line breaks, - % print special symbols as themselves, and - % make each space count - % must do in this order: - \obeylines \uncatcodespecials \sepspaces -} - -% Setup for the @verbatim environment -% -% Real tab expansion -\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount -% -\def\starttabbox{\setbox0=\hbox\bgroup} - -% Allow an option to not replace quotes with a regular directed right -% quote/apostrophe (char 0x27), but instead use the undirected quote -% from cmtt (char 0x0d). The undirected quote is ugly, so don't make it -% the default, but it works for pasting with more pdf viewers (at least -% evince), the lilypond developers report. xpdf does work with the -% regular 0x27. -% -\def\codequoteright{% - \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax - '% - \else - \char'15 - \fi -} -% -% and a similar option for the left quote char vs. a grave accent. -% Modern fonts display ASCII 0x60 as a grave accent, so some people like -% the code environments to do likewise. -% -\def\codequoteleft{% - \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax - `% - \else - \char'22 - \fi -} -% -\begingroup - \catcode`\^^I=\active - \gdef\tabexpand{% - \catcode`\^^I=\active - \def^^I{\leavevmode\egroup - \dimen0=\wd0 % the width so far, or since the previous tab - \divide\dimen0 by\tabw - \multiply\dimen0 by\tabw % compute previous multiple of \tabw - \advance\dimen0 by\tabw % advance to next multiple of \tabw - \wd0=\dimen0 \box0 \starttabbox - }% - } - \catcode`\'=\active - \gdef\rquoteexpand{\catcode\rquoteChar=\active \def'{\codequoteright}}% - % - \catcode`\`=\active - \gdef\lquoteexpand{\catcode\lquoteChar=\active \def`{\codequoteleft}}% - % - \gdef\quoteexpand{\rquoteexpand \lquoteexpand}% -\endgroup - -% start the verbatim environment. -\def\setupverbatim{% - \let\nonarrowing = t% - \nonfillstart - % Easiest (and conventionally used) font for verbatim - \tt - \def\par{\leavevmode\egroup\box0\endgraf}% - \catcode`\`=\active - \tabexpand - \quoteexpand - % Respect line breaks, - % print special symbols as themselves, and - % make each space count - % must do in this order: - \obeylines \uncatcodespecials \sepspaces - \everypar{\starttabbox}% -} - -% Do the @verb magic: verbatim text is quoted by unique -% delimiter characters. Before first delimiter expect a -% right brace, after last delimiter expect closing brace: -% -% \def\doverb'{'#1'}'{#1} -% -% [Knuth] p. 382; only eat outer {} -\begingroup - \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other - \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] -\endgroup -% -\def\verb{\begingroup\setupverb\doverb} -% -% -% Do the @verbatim magic: define the macro \doverbatim so that -% the (first) argument ends when '@end verbatim' is reached, ie: -% -% \def\doverbatim#1@end verbatim{#1} -% -% For Texinfo it's a lot easier than for LaTeX, -% because texinfo's \verbatim doesn't stop at '\end{verbatim}': -% we need not redefine '\', '{' and '}'. -% -% Inspired by LaTeX's verbatim command set [latex.ltx] -% -\begingroup - \catcode`\ =\active - \obeylines % - % ignore everything up to the first ^^M, that's the newline at the end - % of the @verbatim input line itself. Otherwise we get an extra blank - % line in the output. - \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% - % We really want {...\end verbatim} in the body of the macro, but - % without the active space; thus we have to use \xdef and \gobble. -\endgroup -% -\envdef\verbatim{% - \setupverbatim\doverbatim -} -\let\Everbatim = \afterenvbreak - - -% @verbatiminclude FILE - insert text of file in verbatim environment. -% -\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} -% -\def\doverbatiminclude#1{% - {% - \makevalueexpandable - \setupverbatim - \input #1 - \afterenvbreak - }% -} - -% @copying ... @end copying. -% Save the text away for @insertcopying later. -% -% We save the uninterpreted tokens, rather than creating a box. -% Saving the text in a box would be much easier, but then all the -% typesetting commands (@smallbook, font changes, etc.) have to be done -% beforehand -- and a) we want @copying to be done first in the source -% file; b) letting users define the frontmatter in as flexible order as -% possible is very desirable. -% -\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} -\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} -% -\def\insertcopying{% - \begingroup - \parindent = 0pt % paragraph indentation looks wrong on title page - \scanexp\copyingtext - \endgroup -} - -\message{defuns,} -% @defun etc. - -\newskip\defbodyindent \defbodyindent=.4in -\newskip\defargsindent \defargsindent=50pt -\newskip\deflastargmargin \deflastargmargin=18pt - -% Start the processing of @deffn: -\def\startdefun{% - \ifnum\lastpenalty<10000 - \medbreak - \else - % If there are two @def commands in a row, we'll have a \nobreak, - % which is there to keep the function description together with its - % header. But if there's nothing but headers, we need to allow a - % break somewhere. Check specifically for penalty 10002, inserted - % by \defargscommonending, instead of 10000, since the sectioning - % commands also insert a nobreak penalty, and we don't want to allow - % a break between a section heading and a defun. - % - \ifnum\lastpenalty=10002 \penalty2000 \fi - % - % Similarly, after a section heading, do not allow a break. - % But do insert the glue. - \medskip % preceded by discardable penalty, so not a breakpoint - \fi - % - \parindent=0in - \advance\leftskip by \defbodyindent - \exdentamount=\defbodyindent -} - -\def\dodefunx#1{% - % First, check whether we are in the right environment: - \checkenv#1% - % - % As above, allow line break if we have multiple x headers in a row. - % It's not a great place, though. - \ifnum\lastpenalty=10002 \penalty3000 \fi - % - % And now, it's time to reuse the body of the original defun: - \expandafter\gobbledefun#1% -} -\def\gobbledefun#1\startdefun{} - -% \printdefunline \deffnheader{text} -% -\def\printdefunline#1#2{% - \begingroup - % call \deffnheader: - #1#2 \endheader - % common ending: - \interlinepenalty = 10000 - \advance\rightskip by 0pt plus 1fil - \endgraf - \nobreak\vskip -\parskip - \penalty 10002 % signal to \startdefun and \dodefunx - % Some of the @defun-type tags do not enable magic parentheses, - % rendering the following check redundant. But we don't optimize. - \checkparencounts - \endgroup -} - -\def\Edefun{\endgraf\medbreak} - -% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; -% the only thing remainnig is to define \deffnheader. -% -\def\makedefun#1{% - \expandafter\let\csname E#1\endcsname = \Edefun - \edef\temp{\noexpand\domakedefun - \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% - \temp -} - -% \domakedefun \deffn \deffnx \deffnheader -% -% Define \deffn and \deffnx, without parameters. -% \deffnheader has to be defined explicitly. -% -\def\domakedefun#1#2#3{% - \envdef#1{% - \startdefun - \parseargusing\activeparens{\printdefunline#3}% - }% - \def#2{\dodefunx#1}% - \def#3% -} - -%%% Untyped functions: - -% @deffn category name args -\makedefun{deffn}{\deffngeneral{}} - -% @deffn category class name args -\makedefun{defop}#1 {\defopon{#1\ \putwordon}} - -% \defopon {category on}class name args -\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } - -% \deffngeneral {subind}category name args -% -\def\deffngeneral#1#2 #3 #4\endheader{% - % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. - \dosubind{fn}{\code{#3}}{#1}% - \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% -} - -%%% Typed functions: - -% @deftypefn category type name args -\makedefun{deftypefn}{\deftypefngeneral{}} - -% @deftypeop category class type name args -\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} - -% \deftypeopon {category on}class type name args -\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } - -% \deftypefngeneral {subind}category type name args -% -\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% - \dosubind{fn}{\code{#4}}{#1}% - \defname{#2}{#3}{#4}\defunargs{#5\unskip}% -} - -%%% Typed variables: - -% @deftypevr category type var args -\makedefun{deftypevr}{\deftypecvgeneral{}} - -% @deftypecv category class type var args -\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} - -% \deftypecvof {category of}class type var args -\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } - -% \deftypecvgeneral {subind}category type var args -% -\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% - \dosubind{vr}{\code{#4}}{#1}% - \defname{#2}{#3}{#4}\defunargs{#5\unskip}% -} - -%%% Untyped variables: - -% @defvr category var args -\makedefun{defvr}#1 {\deftypevrheader{#1} {} } - -% @defcv category class var args -\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} - -% \defcvof {category of}class var args -\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } - -%%% Type: -% @deftp category name args -\makedefun{deftp}#1 #2 #3\endheader{% - \doind{tp}{\code{#2}}% - \defname{#1}{}{#2}\defunargs{#3\unskip}% -} - -% Remaining @defun-like shortcuts: -\makedefun{defun}{\deffnheader{\putwordDeffunc} } -\makedefun{defmac}{\deffnheader{\putwordDefmac} } -\makedefun{defspec}{\deffnheader{\putwordDefspec} } -\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } -\makedefun{defvar}{\defvrheader{\putwordDefvar} } -\makedefun{defopt}{\defvrheader{\putwordDefopt} } -\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } -\makedefun{defmethod}{\defopon\putwordMethodon} -\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} -\makedefun{defivar}{\defcvof\putwordInstanceVariableof} -\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} - -% \defname, which formats the name of the @def (not the args). -% #1 is the category, such as "Function". -% #2 is the return type, if any. -% #3 is the function name. -% -% We are followed by (but not passed) the arguments, if any. -% -\def\defname#1#2#3{% - % Get the values of \leftskip and \rightskip as they were outside the @def... - \advance\leftskip by -\defbodyindent - % - % How we'll format the type name. Putting it in brackets helps - % distinguish it from the body text that may end up on the next line - % just below it. - \def\temp{#1}% - \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} - % - % Figure out line sizes for the paragraph shape. - % The first line needs space for \box0; but if \rightskip is nonzero, - % we need only space for the part of \box0 which exceeds it: - \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip - % The continuations: - \dimen2=\hsize \advance\dimen2 by -\defargsindent - % (plain.tex says that \dimen1 should be used only as global.) - \parshape 2 0in \dimen0 \defargsindent \dimen2 - % - % Put the type name to the right margin. - \noindent - \hbox to 0pt{% - \hfil\box0 \kern-\hsize - % \hsize has to be shortened this way: - \kern\leftskip - % Intentionally do not respect \rightskip, since we need the space. - }% - % - % Allow all lines to be underfull without complaint: - \tolerance=10000 \hbadness=10000 - \exdentamount=\defbodyindent - {% - % defun fonts. We use typewriter by default (used to be bold) because: - % . we're printing identifiers, they should be in tt in principle. - % . in languages with many accents, such as Czech or French, it's - % common to leave accents off identifiers. The result looks ok in - % tt, but exceedingly strange in rm. - % . we don't want -- and --- to be treated as ligatures. - % . this still does not fix the ?` and !` ligatures, but so far no - % one has made identifiers using them :). - \df \tt - \def\temp{#2}% return value type - \ifx\temp\empty\else \tclose{\temp} \fi - #3% output function name - }% - {\rm\enskip}% hskip 0.5 em of \tenrm - % - \boldbrax - % arguments will be output next, if any. -} - -% Print arguments in slanted roman (not ttsl), inconsistently with using -% tt for the name. This is because literal text is sometimes needed in -% the argument list (groff manual), and ttsl and tt are not very -% distinguishable. Prevent hyphenation at `-' chars. -% -\def\defunargs#1{% - % use sl by default (not ttsl), - % tt for the names. - \df \sl \hyphenchar\font=0 - % - % On the other hand, if an argument has two dashes (for instance), we - % want a way to get ttsl. Let's try @var for that. - \let\var=\ttslanted - #1% - \sl\hyphenchar\font=45 -} - -% We want ()&[] to print specially on the defun line. -% -\def\activeparens{% - \catcode`\(=\active \catcode`\)=\active - \catcode`\[=\active \catcode`\]=\active - \catcode`\&=\active -} - -% Make control sequences which act like normal parenthesis chars. -\let\lparen = ( \let\rparen = ) - -% Be sure that we always have a definition for `(', etc. For example, -% if the fn name has parens in it, \boldbrax will not be in effect yet, -% so TeX would otherwise complain about undefined control sequence. -{ - \activeparens - \global\let(=\lparen \global\let)=\rparen - \global\let[=\lbrack \global\let]=\rbrack - \global\let& = \& - - \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} - \gdef\magicamp{\let&=\amprm} -} - -\newcount\parencount - -% If we encounter &foo, then turn on ()-hacking afterwards -\newif\ifampseen -\def\amprm#1 {\ampseentrue{\bf\ }} - -\def\parenfont{% - \ifampseen - % At the first level, print parens in roman, - % otherwise use the default font. - \ifnum \parencount=1 \rm \fi - \else - % The \sf parens (in \boldbrax) actually are a little bolder than - % the contained text. This is especially needed for [ and ] . - \sf - \fi -} -\def\infirstlevel#1{% - \ifampseen - \ifnum\parencount=1 - #1% - \fi - \fi -} -\def\bfafterword#1 {#1 \bf} - -\def\opnr{% - \global\advance\parencount by 1 - {\parenfont(}% - \infirstlevel \bfafterword -} -\def\clnr{% - {\parenfont)}% - \infirstlevel \sl - \global\advance\parencount by -1 -} - -\newcount\brackcount -\def\lbrb{% - \global\advance\brackcount by 1 - {\bf[}% -} -\def\rbrb{% - {\bf]}% - \global\advance\brackcount by -1 -} - -\def\checkparencounts{% - \ifnum\parencount=0 \else \badparencount \fi - \ifnum\brackcount=0 \else \badbrackcount \fi -} -\def\badparencount{% - \errmessage{Unbalanced parentheses in @def}% - \global\parencount=0 -} -\def\badbrackcount{% - \errmessage{Unbalanced square braces in @def}% - \global\brackcount=0 -} - - -\message{macros,} -% @macro. - -% To do this right we need a feature of e-TeX, \scantokens, -% which we arrange to emulate with a temporary file in ordinary TeX. -\ifx\eTeXversion\undefined - \newwrite\macscribble - \def\scantokens#1{% - \toks0={#1}% - \immediate\openout\macscribble=\jobname.tmp - \immediate\write\macscribble{\the\toks0}% - \immediate\closeout\macscribble - \input \jobname.tmp - } -\fi - -\def\scanmacro#1{% - \begingroup - \newlinechar`\^^M - \let\xeatspaces\eatspaces - % Undo catcode changes of \startcontents and \doprintindex - % When called from @insertcopying or (short)caption, we need active - % backslash to get it printed correctly. Previously, we had - % \catcode`\\=\other instead. We'll see whether a problem appears - % with macro expansion. --kasal, 19aug04 - \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ - % ... and \example - \spaceisspace - % - % Append \endinput to make sure that TeX does not see the ending newline. - % I've verified that it is necessary both for e-TeX and for ordinary TeX - % --kasal, 29nov03 - \scantokens{#1\endinput}% - \endgroup -} - -\def\scanexp#1{% - \edef\temp{\noexpand\scanmacro{#1}}% - \temp -} - -\newcount\paramno % Count of parameters -\newtoks\macname % Macro name -\newif\ifrecursive % Is it recursive? - -% List of all defined macros in the form -% \definedummyword\macro1\definedummyword\macro2... -% Currently is also contains all @aliases; the list can be split -% if there is a need. -\def\macrolist{} - -% Add the macro to \macrolist -\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} -\def\addtomacrolistxxx#1{% - \toks0 = \expandafter{\macrolist\definedummyword#1}% - \xdef\macrolist{\the\toks0}% -} - -% Utility routines. -% This does \let #1 = #2, with \csnames; that is, -% \let \csname#1\endcsname = \csname#2\endcsname -% (except of course we have to play expansion games). -% -\def\cslet#1#2{% - \expandafter\let - \csname#1\expandafter\endcsname - \csname#2\endcsname -} - -% Trim leading and trailing spaces off a string. -% Concepts from aro-bend problem 15 (see CTAN). -{\catcode`\@=11 -\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} -\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} -\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} -\def\unbrace#1{#1} -\unbrace{\gdef\trim@@@ #1 } #2@{#1} -} - -% Trim a single trailing ^^M off a string. -{\catcode`\^^M=\other \catcode`\Q=3% -\gdef\eatcr #1{\eatcra #1Q^^MQ}% -\gdef\eatcra#1^^MQ{\eatcrb#1Q}% -\gdef\eatcrb#1Q#2Q{#1}% -} - -% Macro bodies are absorbed as an argument in a context where -% all characters are catcode 10, 11 or 12, except \ which is active -% (as in normal texinfo). It is necessary to change the definition of \. - -% It's necessary to have hard CRs when the macro is executed. This is -% done by making ^^M (\endlinechar) catcode 12 when reading the macro -% body, and then making it the \newlinechar in \scanmacro. - -\def\scanctxt{% - \catcode`\"=\other - \catcode`\+=\other - \catcode`\<=\other - \catcode`\>=\other - \catcode`\@=\other - \catcode`\^=\other - \catcode`\_=\other - \catcode`\|=\other - \catcode`\~=\other -} - -\def\scanargctxt{% - \scanctxt - \catcode`\\=\other - \catcode`\^^M=\other -} - -\def\macrobodyctxt{% - \scanctxt - \catcode`\{=\other - \catcode`\}=\other - \catcode`\^^M=\other - \usembodybackslash -} - -\def\macroargctxt{% - \scanctxt - \catcode`\\=\other -} - -% \mbodybackslash is the definition of \ in @macro bodies. -% It maps \foo\ => \csname macarg.foo\endcsname => #N -% where N is the macro parameter number. -% We define \csname macarg.\endcsname to be \realbackslash, so -% \\ in macro replacement text gets you a backslash. - -{\catcode`@=0 @catcode`@\=@active - @gdef@usembodybackslash{@let\=@mbodybackslash} - @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} -} -\expandafter\def\csname macarg.\endcsname{\realbackslash} - -\def\macro{\recursivefalse\parsearg\macroxxx} -\def\rmacro{\recursivetrue\parsearg\macroxxx} - -\def\macroxxx#1{% - \getargs{#1}% now \macname is the macname and \argl the arglist - \ifx\argl\empty % no arguments - \paramno=0% - \else - \expandafter\parsemargdef \argl;% - \fi - \if1\csname ismacro.\the\macname\endcsname - \message{Warning: redefining \the\macname}% - \else - \expandafter\ifx\csname \the\macname\endcsname \relax - \else \errmessage{Macro name \the\macname\space already defined}\fi - \global\cslet{macsave.\the\macname}{\the\macname}% - \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% - \addtomacrolist{\the\macname}% - \fi - \begingroup \macrobodyctxt - \ifrecursive \expandafter\parsermacbody - \else \expandafter\parsemacbody - \fi} - -\parseargdef\unmacro{% - \if1\csname ismacro.#1\endcsname - \global\cslet{#1}{macsave.#1}% - \global\expandafter\let \csname ismacro.#1\endcsname=0% - % Remove the macro name from \macrolist: - \begingroup - \expandafter\let\csname#1\endcsname \relax - \let\definedummyword\unmacrodo - \xdef\macrolist{\macrolist}% - \endgroup - \else - \errmessage{Macro #1 not defined}% - \fi -} - -% Called by \do from \dounmacro on each macro. The idea is to omit any -% macro definitions that have been changed to \relax. -% -\def\unmacrodo#1{% - \ifx #1\relax - % remove this - \else - \noexpand\definedummyword \noexpand#1% - \fi -} - -% This makes use of the obscure feature that if the last token of a -% is #, then the preceding argument is delimited by -% an opening brace, and that opening brace is not consumed. -\def\getargs#1{\getargsxxx#1{}} -\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} -\def\getmacname #1 #2\relax{\macname={#1}} -\def\getmacargs#1{\def\argl{#1}} - -% Parse the optional {params} list. Set up \paramno and \paramlist -% so \defmacro knows what to do. Define \macarg.blah for each blah -% in the params list, to be ##N where N is the position in that list. -% That gets used by \mbodybackslash (above). - -% We need to get `macro parameter char #' into several definitions. -% The technique used is stolen from LaTeX: let \hash be something -% unexpandable, insert that wherever you need a #, and then redefine -% it to # just before using the token list produced. -% -% The same technique is used to protect \eatspaces till just before -% the macro is used. - -\def\parsemargdef#1;{\paramno=0\def\paramlist{}% - \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} -\def\parsemargdefxxx#1,{% - \if#1;\let\next=\relax - \else \let\next=\parsemargdefxxx - \advance\paramno by 1% - \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname - {\xeatspaces{\hash\the\paramno}}% - \edef\paramlist{\paramlist\hash\the\paramno,}% - \fi\next} - -% These two commands read recursive and nonrecursive macro bodies. -% (They're different since rec and nonrec macros end differently.) - -\long\def\parsemacbody#1@end macro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% -\long\def\parsermacbody#1@end rmacro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% - -% This defines the macro itself. There are six cases: recursive and -% nonrecursive macros of zero, one, and many arguments. -% Much magic with \expandafter here. -% \xdef is used so that macro definitions will survive the file -% they're defined in; @include reads the file inside a group. -\def\defmacro{% - \let\hash=##% convert placeholders to macro parameter chars - \ifrecursive - \ifcase\paramno - % 0 - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\scanmacro{\temp}}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline - \expandafter\noexpand\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup\noexpand\scanmacro{\temp}}% - \else % many - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{\egroup\noexpand\scanmacro{\temp}}% - \fi - \else - \ifcase\paramno - % 0 - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline - \expandafter\noexpand\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \else % many - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \expandafter\noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \fi - \fi} - -\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} - -% \braceorline decides whether the next nonwhitespace character is a -% {. If so it reads up to the closing }, if not, it reads the whole -% line. Whatever was read is then fed to the next control sequence -% as an argument (by \parsebrace or \parsearg) -\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} -\def\braceorlinexxx{% - \ifx\nchar\bgroup\else - \expandafter\parsearg - \fi \macnamexxx} - - -% @alias. -% We need some trickery to remove the optional spaces around the equal -% sign. Just make them active and then expand them all to nothing. -\def\alias{\parseargusing\obeyspaces\aliasxxx} -\def\aliasxxx #1{\aliasyyy#1\relax} -\def\aliasyyy #1=#2\relax{% - {% - \expandafter\let\obeyedspace=\empty - \addtomacrolist{#1}% - \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% - }% - \next -} - - -\message{cross references,} - -\newwrite\auxfile - -\newif\ifhavexrefs % True if xref values are known. -\newif\ifwarnedxrefs % True if we warned once that they aren't known. - -% @inforef is relatively simple. -\def\inforef #1{\inforefzzz #1,,,,**} -\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, - node \samp{\ignorespaces#1{}}} - -% @node's only job in TeX is to define \lastnode, which is used in -% cross-references. The @node line might or might not have commas, and -% might or might not have spaces before the first comma, like: -% @node foo , bar , ... -% We don't want such trailing spaces in the node name. -% -\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} -% -% also remove a trailing comma, in case of something like this: -% @node Help-Cross, , , Cross-refs -\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} -\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} - -\let\nwnode=\node -\let\lastnode=\empty - -% Write a cross-reference definition for the current node. #1 is the -% type (Ynumbered, Yappendix, Ynothing). -% -\def\donoderef#1{% - \ifx\lastnode\empty\else - \setref{\lastnode}{#1}% - \global\let\lastnode=\empty - \fi -} - -% @anchor{NAME} -- define xref target at arbitrary point. -% -\newcount\savesfregister -% -\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} -\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} -\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} - -% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an -% anchor), which consists of three parts: -% 1) NAME-title - the current sectioning name taken from \thissection, -% or the anchor name. -% 2) NAME-snt - section number and type, passed as the SNT arg, or -% empty for anchors. -% 3) NAME-pg - the page number. -% -% This is called from \donoderef, \anchor, and \dofloat. In the case of -% floats, there is an additional part, which is not written here: -% 4) NAME-lof - the text as it should appear in a @listoffloats. -% -\def\setref#1#2{% - \pdfmkdest{#1}% - \iflinks - {% - \atdummies % preserve commands, but don't expand them - \edef\writexrdef##1##2{% - \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef - ##1}{##2}}% these are parameters of \writexrdef - }% - \toks0 = \expandafter{\thissection}% - \immediate \writexrdef{title}{\the\toks0 }% - \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. - \writexrdef{pg}{\folio}% will be written later, during \shipout - }% - \fi -} - -% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is -% the node name, #2 the name of the Info cross-reference, #3 the printed -% node name, #4 the name of the Info file, #5 the name of the printed -% manual. All but the node name can be omitted. -% -\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} -\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} -\def\ref#1{\xrefX[#1,,,,,,,]} -\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup - \unsepspaces - \def\printedmanual{\ignorespaces #5}% - \def\printedrefname{\ignorespaces #3}% - \setbox1=\hbox{\printedmanual\unskip}% - \setbox0=\hbox{\printedrefname\unskip}% - \ifdim \wd0 = 0pt - % No printed node name was explicitly given. - \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax - % Use the node name inside the square brackets. - \def\printedrefname{\ignorespaces #1}% - \else - % Use the actual chapter/section title appear inside - % the square brackets. Use the real section title if we have it. - \ifdim \wd1 > 0pt - % It is in another manual, so we don't have it. - \def\printedrefname{\ignorespaces #1}% - \else - \ifhavexrefs - % We know the real title if we have the xref values. - \def\printedrefname{\refx{#1-title}{}}% - \else - % Otherwise just copy the Info node name. - \def\printedrefname{\ignorespaces #1}% - \fi% - \fi - \fi - \fi - % - % Make link in pdf output. - \ifpdf - \leavevmode - \getfilename{#4}% - {\turnoffactive - % See comments at \activebackslashdouble. - {\activebackslashdouble \xdef\pdfxrefdest{#1}% - \backslashparens\pdfxrefdest}% - % - \ifnum\filenamelength>0 - \startlink attr{/Border [0 0 0]}% - goto file{\the\filename.pdf} name{\pdfxrefdest}% - \else - \startlink attr{/Border [0 0 0]}% - goto name{\pdfmkpgn{\pdfxrefdest}}% - \fi - }% - \linkcolor - \fi - % - % Float references are printed completely differently: "Figure 1.2" - % instead of "[somenode], p.3". We distinguish them by the - % LABEL-title being set to a magic string. - {% - % Have to otherify everything special to allow the \csname to - % include an _ in the xref name, etc. - \indexnofonts - \turnoffactive - \expandafter\global\expandafter\let\expandafter\Xthisreftitle - \csname XR#1-title\endcsname - }% - \iffloat\Xthisreftitle - % If the user specified the print name (third arg) to the ref, - % print it instead of our usual "Figure 1.2". - \ifdim\wd0 = 0pt - \refx{#1-snt}{}% - \else - \printedrefname - \fi - % - % if the user also gave the printed manual name (fifth arg), append - % "in MANUALNAME". - \ifdim \wd1 > 0pt - \space \putwordin{} \cite{\printedmanual}% - \fi - \else - % node/anchor (non-float) references. - % - % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not - % insert empty discretionaries after hyphens, which means that it will - % not find a line break at a hyphen in a node names. Since some manuals - % are best written with fairly long node names, containing hyphens, this - % is a loss. Therefore, we give the text of the node name again, so it - % is as if TeX is seeing it for the first time. - \ifdim \wd1 > 0pt - \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% - \else - % _ (for example) has to be the character _ for the purposes of the - % control sequence corresponding to the node, but it has to expand - % into the usual \leavevmode...\vrule stuff for purposes of - % printing. So we \turnoffactive for the \refx-snt, back on for the - % printing, back off for the \refx-pg. - {\turnoffactive - % Only output a following space if the -snt ref is nonempty; for - % @unnumbered and @anchor, it won't be. - \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% - \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi - }% - % output the `[mynode]' via a macro so it can be overridden. - \xrefprintnodename\printedrefname - % - % But we always want a comma and a space: - ,\space - % - % output the `page 3'. - \turnoffactive \putwordpage\tie\refx{#1-pg}{}% - \fi - \fi - \endlink -\endgroup} - -% This macro is called from \xrefX for the `[nodename]' part of xref -% output. It's a separate macro only so it can be changed more easily, -% since square brackets don't work well in some documents. Particularly -% one that Bob is working on :). -% -\def\xrefprintnodename#1{[#1]} - -% Things referred to by \setref. -% -\def\Ynothing{} -\def\Yomitfromtoc{} -\def\Ynumbered{% - \ifnum\secno=0 - \putwordChapter@tie \the\chapno - \else \ifnum\subsecno=0 - \putwordSection@tie \the\chapno.\the\secno - \else \ifnum\subsubsecno=0 - \putwordSection@tie \the\chapno.\the\secno.\the\subsecno - \else - \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno - \fi\fi\fi -} -\def\Yappendix{% - \ifnum\secno=0 - \putwordAppendix@tie @char\the\appendixno{}% - \else \ifnum\subsecno=0 - \putwordSection@tie @char\the\appendixno.\the\secno - \else \ifnum\subsubsecno=0 - \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno - \else - \putwordSection@tie - @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno - \fi\fi\fi -} - -% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. -% If its value is nonempty, SUFFIX is output afterward. -% -\def\refx#1#2{% - {% - \indexnofonts - \otherbackslash - \expandafter\global\expandafter\let\expandafter\thisrefX - \csname XR#1\endcsname - }% - \ifx\thisrefX\relax - % If not defined, say something at least. - \angleleft un\-de\-fined\angleright - \iflinks - \ifhavexrefs - \message{\linenumber Undefined cross reference `#1'.}% - \else - \ifwarnedxrefs\else - \global\warnedxrefstrue - \message{Cross reference values unknown; you must run TeX again.}% - \fi - \fi - \fi - \else - % It's defined, so just use it. - \thisrefX - \fi - #2% Output the suffix in any case. -} - -% This is the macro invoked by entries in the aux file. Usually it's -% just a \def (we prepend XR to the control sequence name to avoid -% collisions). But if this is a float type, we have more work to do. -% -\def\xrdef#1#2{% - \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. - % - % Was that xref control sequence that we just defined for a float? - \expandafter\iffloat\csname XR#1\endcsname - % it was a float, and we have the (safe) float type in \iffloattype. - \expandafter\let\expandafter\floatlist - \csname floatlist\iffloattype\endcsname - % - % Is this the first time we've seen this float type? - \expandafter\ifx\floatlist\relax - \toks0 = {\do}% yes, so just \do - \else - % had it before, so preserve previous elements in list. - \toks0 = \expandafter{\floatlist\do}% - \fi - % - % Remember this xref in the control sequence \floatlistFLOATTYPE, - % for later use in \listoffloats. - \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% - \fi -} - -% Read the last existing aux file, if any. No error if none exists. -% -\def\tryauxfile{% - \openin 1 \jobname.aux - \ifeof 1 \else - \readdatafile{aux}% - \global\havexrefstrue - \fi - \closein 1 -} - -\def\setupdatafile{% - \catcode`\^^@=\other - \catcode`\^^A=\other - \catcode`\^^B=\other - \catcode`\^^C=\other - \catcode`\^^D=\other - \catcode`\^^E=\other - \catcode`\^^F=\other - \catcode`\^^G=\other - \catcode`\^^H=\other - \catcode`\^^K=\other - \catcode`\^^L=\other - \catcode`\^^N=\other - \catcode`\^^P=\other - \catcode`\^^Q=\other - \catcode`\^^R=\other - \catcode`\^^S=\other - \catcode`\^^T=\other - \catcode`\^^U=\other - \catcode`\^^V=\other - \catcode`\^^W=\other - \catcode`\^^X=\other - \catcode`\^^Z=\other - \catcode`\^^[=\other - \catcode`\^^\=\other - \catcode`\^^]=\other - \catcode`\^^^=\other - \catcode`\^^_=\other - % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. - % in xref tags, i.e., node names. But since ^^e4 notation isn't - % supported in the main text, it doesn't seem desirable. Furthermore, - % that is not enough: for node names that actually contain a ^ - % character, we would end up writing a line like this: 'xrdef {'hat - % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first - % argument, and \hat is not an expandable control sequence. It could - % all be worked out, but why? Either we support ^^ or we don't. - % - % The other change necessary for this was to define \auxhat: - % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter - % and then to call \auxhat in \setq. - % - \catcode`\^=\other - % - % Special characters. Should be turned off anyway, but... - \catcode`\~=\other - \catcode`\[=\other - \catcode`\]=\other - \catcode`\"=\other - \catcode`\_=\other - \catcode`\|=\other - \catcode`\<=\other - \catcode`\>=\other - \catcode`\$=\other - \catcode`\#=\other - \catcode`\&=\other - \catcode`\%=\other - \catcode`+=\other % avoid \+ for paranoia even though we've turned it off - % - % This is to support \ in node names and titles, since the \ - % characters end up in a \csname. It's easier than - % leaving it active and making its active definition an actual \ - % character. What I don't understand is why it works in the *value* - % of the xrdef. Seems like it should be a catcode12 \, and that - % should not typeset properly. But it works, so I'm moving on for - % now. --karl, 15jan04. - \catcode`\\=\other - % - % Make the characters 128-255 be printing characters. - {% - \count1=128 - \def\loop{% - \catcode\count1=\other - \advance\count1 by 1 - \ifnum \count1<256 \loop \fi - }% - }% - % - % @ is our escape character in .aux files, and we need braces. - \catcode`\{=1 - \catcode`\}=2 - \catcode`\@=0 -} - -\def\readdatafile#1{% -\begingroup - \setupdatafile - \input\jobname.#1 -\endgroup} - -\message{insertions,} -% including footnotes. - -\newcount \footnoteno - -% The trailing space in the following definition for supereject is -% vital for proper filling; pages come out unaligned when you do a -% pagealignmacro call if that space before the closing brace is -% removed. (Generally, numeric constants should always be followed by a -% space to prevent strange expansion errors.) -\def\supereject{\par\penalty -20000\footnoteno =0 } - -% @footnotestyle is meaningful for info output only. -\let\footnotestyle=\comment - -{\catcode `\@=11 -% -% Auto-number footnotes. Otherwise like plain. -\gdef\footnote{% - \let\indent=\ptexindent - \let\noindent=\ptexnoindent - \global\advance\footnoteno by \@ne - \edef\thisfootno{$^{\the\footnoteno}$}% - % - % In case the footnote comes at the end of a sentence, preserve the - % extra spacing after we do the footnote number. - \let\@sf\empty - \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi - % - % Remove inadvertent blank space before typesetting the footnote number. - \unskip - \thisfootno\@sf - \dofootnote -}% - -% Don't bother with the trickery in plain.tex to not require the -% footnote text as a parameter. Our footnotes don't need to be so general. -% -% Oh yes, they do; otherwise, @ifset (and anything else that uses -% \parseargline) fails inside footnotes because the tokens are fixed when -% the footnote is read. --karl, 16nov96. -% -\gdef\dofootnote{% - \insert\footins\bgroup - % We want to typeset this text as a normal paragraph, even if the - % footnote reference occurs in (for example) a display environment. - % So reset some parameters. - \hsize=\pagewidth - \interlinepenalty\interfootnotelinepenalty - \splittopskip\ht\strutbox % top baseline for broken footnotes - \splitmaxdepth\dp\strutbox - \floatingpenalty\@MM - \leftskip\z@skip - \rightskip\z@skip - \spaceskip\z@skip - \xspaceskip\z@skip - \parindent\defaultparindent - % - \smallfonts \rm - % - % Because we use hanging indentation in footnotes, a @noindent appears - % to exdent this text, so make it be a no-op. makeinfo does not use - % hanging indentation so @noindent can still be needed within footnote - % text after an @example or the like (not that this is good style). - \let\noindent = \relax - % - % Hang the footnote text off the number. Use \everypar in case the - % footnote extends for more than one paragraph. - \everypar = {\hang}% - \textindent{\thisfootno}% - % - % Don't crash into the line above the footnote text. Since this - % expands into a box, it must come within the paragraph, lest it - % provide a place where TeX can split the footnote. - \footstrut - \futurelet\next\fo@t -} -}%end \catcode `\@=11 - -% In case a @footnote appears in a vbox, save the footnote text and create -% the real \insert just after the vbox finished. Otherwise, the insertion -% would be lost. -% Similarily, if a @footnote appears inside an alignment, save the footnote -% text to a box and make the \insert when a row of the table is finished. -% And the same can be done for other insert classes. --kasal, 16nov03. - -% Replace the \insert primitive by a cheating macro. -% Deeper inside, just make sure that the saved insertions are not spilled -% out prematurely. -% -\def\startsavinginserts{% - \ifx \insert\ptexinsert - \let\insert\saveinsert - \else - \let\checkinserts\relax - \fi -} - -% This \insert replacement works for both \insert\footins{foo} and -% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. -% -\def\saveinsert#1{% - \edef\next{\noexpand\savetobox \makeSAVEname#1}% - \afterassignment\next - % swallow the left brace - \let\temp = -} -\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} -\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} - -\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} - -\def\placesaveins#1{% - \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname - {\box#1}% -} - -% eat @SAVE -- beware, all of them have catcode \other: -{ - \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) - \gdef\gobblesave @SAVE{} -} - -% initialization: -\def\newsaveins #1{% - \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% - \next -} -\def\newsaveinsX #1{% - \csname newbox\endcsname #1% - \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts - \checksaveins #1}% -} - -% initialize: -\let\checkinserts\empty -\newsaveins\footins -\newsaveins\margin - - -% @image. We use the macros from epsf.tex to support this. -% If epsf.tex is not installed and @image is used, we complain. -% -% Check for and read epsf.tex up front. If we read it only at @image -% time, we might be inside a group, and then its definitions would get -% undone and the next image would fail. -\openin 1 = epsf.tex -\ifeof 1 \else - % Do not bother showing banner with epsf.tex v2.7k (available in - % doc/epsf.tex and on ctan). - \def\epsfannounce{\toks0 = }% - \input epsf.tex -\fi -\closein 1 -% -% We will only complain once about lack of epsf.tex. -\newif\ifwarnednoepsf -\newhelp\noepsfhelp{epsf.tex must be installed for images to - work. It is also included in the Texinfo distribution, or you can get - it from ftp://tug.org/tex/epsf.tex.} -% -\def\image#1{% - \ifx\epsfbox\undefined - \ifwarnednoepsf \else - \errhelp = \noepsfhelp - \errmessage{epsf.tex not found, images will be ignored}% - \global\warnednoepsftrue - \fi - \else - \imagexxx #1,,,,,\finish - \fi -} -% -% Arguments to @image: -% #1 is (mandatory) image filename; we tack on .eps extension. -% #2 is (optional) width, #3 is (optional) height. -% #4 is (ignored optional) html alt text. -% #5 is (ignored optional) extension. -% #6 is just the usual extra ignored arg for parsing this stuff. -\newif\ifimagevmode -\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup - \catcode`\^^M = 5 % in case we're inside an example - \normalturnoffactive % allow _ et al. in names - % If the image is by itself, center it. - \ifvmode - \imagevmodetrue - \nobreak\bigskip - % Usually we'll have text after the image which will insert - % \parskip glue, so insert it here too to equalize the space - % above and below. - \nobreak\vskip\parskip - \nobreak - \line\bgroup - \fi - % - % Output the image. - \ifpdf - \dopdfimage{#1}{#2}{#3}% - \else - % \epsfbox itself resets \epsf?size at each figure. - \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi - \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi - \epsfbox{#1.eps}% - \fi - % - \ifimagevmode \egroup \bigbreak \fi % space after the image -\endgroup} - - -% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, -% etc. We don't actually implement floating yet, we always include the -% float "here". But it seemed the best name for the future. -% -\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} - -% There may be a space before second and/or third parameter; delete it. -\def\eatcommaspace#1, {#1,} - -% #1 is the optional FLOATTYPE, the text label for this float, typically -% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, -% this float will not be numbered and cannot be referred to. -% -% #2 is the optional xref label. Also must be present for the float to -% be referable. -% -% #3 is the optional positioning argument; for now, it is ignored. It -% will somehow specify the positions allowed to float to (here, top, bottom). -% -% We keep a separate counter for each FLOATTYPE, which we reset at each -% chapter-level command. -\let\resetallfloatnos=\empty -% -\def\dofloat#1,#2,#3,#4\finish{% - \let\thiscaption=\empty - \let\thisshortcaption=\empty - % - % don't lose footnotes inside @float. - % - % BEWARE: when the floats start float, we have to issue warning whenever an - % insert appears inside a float which could possibly float. --kasal, 26may04 - % - \startsavinginserts - % - % We can't be used inside a paragraph. - \par - % - \vtop\bgroup - \def\floattype{#1}% - \def\floatlabel{#2}% - \def\floatloc{#3}% we do nothing with this yet. - % - \ifx\floattype\empty - \let\safefloattype=\empty - \else - {% - % the floattype might have accents or other special characters, - % but we need to use it in a control sequence name. - \indexnofonts - \turnoffactive - \xdef\safefloattype{\floattype}% - }% - \fi - % - % If label is given but no type, we handle that as the empty type. - \ifx\floatlabel\empty \else - % We want each FLOATTYPE to be numbered separately (Figure 1, - % Table 1, Figure 2, ...). (And if no label, no number.) - % - \expandafter\getfloatno\csname\safefloattype floatno\endcsname - \global\advance\floatno by 1 - % - {% - % This magic value for \thissection is output by \setref as the - % XREFLABEL-title value. \xrefX uses it to distinguish float - % labels (which have a completely different output format) from - % node and anchor labels. And \xrdef uses it to construct the - % lists of floats. - % - \edef\thissection{\floatmagic=\safefloattype}% - \setref{\floatlabel}{Yfloat}% - }% - \fi - % - % start with \parskip glue, I guess. - \vskip\parskip - % - % Don't suppress indentation if a float happens to start a section. - \restorefirstparagraphindent -} - -% we have these possibilities: -% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap -% @float Foo,lbl & no caption: Foo 1.1 -% @float Foo & @caption{Cap}: Foo: Cap -% @float Foo & no caption: Foo -% @float ,lbl & Caption{Cap}: 1.1: Cap -% @float ,lbl & no caption: 1.1 -% @float & @caption{Cap}: Cap -% @float & no caption: -% -\def\Efloat{% - \let\floatident = \empty - % - % In all cases, if we have a float type, it comes first. - \ifx\floattype\empty \else \def\floatident{\floattype}\fi - % - % If we have an xref label, the number comes next. - \ifx\floatlabel\empty \else - \ifx\floattype\empty \else % if also had float type, need tie first. - \appendtomacro\floatident{\tie}% - \fi - % the number. - \appendtomacro\floatident{\chaplevelprefix\the\floatno}% - \fi - % - % Start the printed caption with what we've constructed in - % \floatident, but keep it separate; we need \floatident again. - \let\captionline = \floatident - % - \ifx\thiscaption\empty \else - \ifx\floatident\empty \else - \appendtomacro\captionline{: }% had ident, so need a colon between - \fi - % - % caption text. - \appendtomacro\captionline{\scanexp\thiscaption}% - \fi - % - % If we have anything to print, print it, with space before. - % Eventually this needs to become an \insert. - \ifx\captionline\empty \else - \vskip.5\parskip - \captionline - % - % Space below caption. - \vskip\parskip - \fi - % - % If have an xref label, write the list of floats info. Do this - % after the caption, to avoid chance of it being a breakpoint. - \ifx\floatlabel\empty \else - % Write the text that goes in the lof to the aux file as - % \floatlabel-lof. Besides \floatident, we include the short - % caption if specified, else the full caption if specified, else nothing. - {% - \atdummies - % - % since we read the caption text in the macro world, where ^^M - % is turned into a normal character, we have to scan it back, so - % we don't write the literal three characters "^^M" into the aux file. - \scanexp{% - \xdef\noexpand\gtemp{% - \ifx\thisshortcaption\empty - \thiscaption - \else - \thisshortcaption - \fi - }% - }% - \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident - \ifx\gtemp\empty \else : \gtemp \fi}}% - }% - \fi - \egroup % end of \vtop - % - % place the captured inserts - % - % BEWARE: when the floats start floating, we have to issue warning - % whenever an insert appears inside a float which could possibly - % float. --kasal, 26may04 - % - \checkinserts -} - -% Append the tokens #2 to the definition of macro #1, not expanding either. -% -\def\appendtomacro#1#2{% - \expandafter\def\expandafter#1\expandafter{#1#2}% -} - -% @caption, @shortcaption -% -\def\caption{\docaption\thiscaption} -\def\shortcaption{\docaption\thisshortcaption} -\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} -\def\defcaption#1#2{\egroup \def#1{#2}} - -% The parameter is the control sequence identifying the counter we are -% going to use. Create it if it doesn't exist and assign it to \floatno. -\def\getfloatno#1{% - \ifx#1\relax - % Haven't seen this figure type before. - \csname newcount\endcsname #1% - % - % Remember to reset this floatno at the next chap. - \expandafter\gdef\expandafter\resetallfloatnos - \expandafter{\resetallfloatnos #1=0 }% - \fi - \let\floatno#1% -} - -% \setref calls this to get the XREFLABEL-snt value. We want an @xref -% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we -% first read the @float command. -% -\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% - -% Magic string used for the XREFLABEL-title value, so \xrefX can -% distinguish floats from other xref types. -\def\floatmagic{!!float!!} - -% #1 is the control sequence we are passed; we expand into a conditional -% which is true if #1 represents a float ref. That is, the magic -% \thissection value which we \setref above. -% -\def\iffloat#1{\expandafter\doiffloat#1==\finish} -% -% #1 is (maybe) the \floatmagic string. If so, #2 will be the -% (safe) float type for this float. We set \iffloattype to #2. -% -\def\doiffloat#1=#2=#3\finish{% - \def\temp{#1}% - \def\iffloattype{#2}% - \ifx\temp\floatmagic -} - -% @listoffloats FLOATTYPE - print a list of floats like a table of contents. -% -\parseargdef\listoffloats{% - \def\floattype{#1}% floattype - {% - % the floattype might have accents or other special characters, - % but we need to use it in a control sequence name. - \indexnofonts - \turnoffactive - \xdef\safefloattype{\floattype}% - }% - % - % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. - \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax - \ifhavexrefs - % if the user said @listoffloats foo but never @float foo. - \message{\linenumber No `\safefloattype' floats to list.}% - \fi - \else - \begingroup - \leftskip=\tocindent % indent these entries like a toc - \let\do=\listoffloatsdo - \csname floatlist\safefloattype\endcsname - \endgroup - \fi -} - -% This is called on each entry in a list of floats. We're passed the -% xref label, in the form LABEL-title, which is how we save it in the -% aux file. We strip off the -title and look up \XRLABEL-lof, which -% has the text we're supposed to typeset here. -% -% Figures without xref labels will not be included in the list (since -% they won't appear in the aux file). -% -\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} -\def\listoffloatsdoentry#1-title\finish{{% - % Can't fully expand XR#1-lof because it can contain anything. Just - % pass the control sequence. On the other hand, XR#1-pg is just the - % page number, and we want to fully expand that so we can get a link - % in pdf output. - \toksA = \expandafter{\csname XR#1-lof\endcsname}% - % - % use the same \entry macro we use to generate the TOC and index. - \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% - \writeentry -}} - -\message{localization,} -% and i18n. - -% @documentlanguage is usually given very early, just after -% @setfilename. If done too late, it may not override everything -% properly. Single argument is the language abbreviation. -% It would be nice if we could set up a hyphenation file here. -% -\parseargdef\documentlanguage{% - \tex % read txi-??.tex file in plain TeX. - % Read the file if it exists. - \openin 1 txi-#1.tex - \ifeof 1 - \errhelp = \nolanghelp - \errmessage{Cannot read language file txi-#1.tex}% - \else - \input txi-#1.tex - \fi - \closein 1 - \endgroup -} -\newhelp\nolanghelp{The given language definition file cannot be found or -is empty. Maybe you need to install it? In the current directory -should work if nowhere else does.} - - -% @documentencoding should change something in TeX eventually, most -% likely, but for now just recognize it. -\let\documentencoding = \comment - - -% Page size parameters. -% -\newdimen\defaultparindent \defaultparindent = 15pt - -\chapheadingskip = 15pt plus 4pt minus 2pt -\secheadingskip = 12pt plus 3pt minus 2pt -\subsecheadingskip = 9pt plus 2pt minus 2pt - -% Prevent underfull vbox error messages. -\vbadness = 10000 - -% Don't be so finicky about underfull hboxes, either. -\hbadness = 2000 - -% Following George Bush, just get rid of widows and orphans. -\widowpenalty=10000 -\clubpenalty=10000 - -% Use TeX 3.0's \emergencystretch to help line breaking, but if we're -% using an old version of TeX, don't do anything. We want the amount of -% stretch added to depend on the line length, hence the dependence on -% \hsize. We call this whenever the paper size is set. -% -\def\setemergencystretch{% - \ifx\emergencystretch\thisisundefined - % Allow us to assign to \emergencystretch anyway. - \def\emergencystretch{\dimen0}% - \else - \emergencystretch = .15\hsize - \fi -} - -% Parameters in order: 1) textheight; 2) textwidth; -% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; -% 7) physical page height; 8) physical page width. -% -% We also call \setleading{\textleading}, so the caller should define -% \textleading. The caller should also set \parskip. -% -\def\internalpagesizes#1#2#3#4#5#6#7#8{% - \voffset = #3\relax - \topskip = #6\relax - \splittopskip = \topskip - % - \vsize = #1\relax - \advance\vsize by \topskip - \outervsize = \vsize - \advance\outervsize by 2\topandbottommargin - \pageheight = \vsize - % - \hsize = #2\relax - \outerhsize = \hsize - \advance\outerhsize by 0.5in - \pagewidth = \hsize - % - \normaloffset = #4\relax - \bindingoffset = #5\relax - % - \ifpdf - \pdfpageheight #7\relax - \pdfpagewidth #8\relax - \fi - % - \setleading{\textleading} - % - \parindent = \defaultparindent - \setemergencystretch -} - -% @letterpaper (the default). -\def\letterpaper{{\globaldefs = 1 - \parskip = 3pt plus 2pt minus 1pt - \textleading = 13.2pt - % - % If page is nothing but text, make it come out even. - \internalpagesizes{46\baselineskip}{6in}% - {\voffset}{.25in}% - {\bindingoffset}{36pt}% - {11in}{8.5in}% -}} - -% Use @smallbook to reset parameters for 7x9.25 trim size. -\def\smallbook{{\globaldefs = 1 - \parskip = 2pt plus 1pt - \textleading = 12pt - % - \internalpagesizes{7.5in}{5in}% - {\voffset}{.25in}% - {\bindingoffset}{16pt}% - {9.25in}{7in}% - % - \lispnarrowing = 0.3in - \tolerance = 700 - \hfuzz = 1pt - \contentsrightmargin = 0pt - \defbodyindent = .5cm -}} - -% Use @smallerbook to reset parameters for 6x9 trim size. -% (Just testing, parameters still in flux.) -\def\smallerbook{{\globaldefs = 1 - \parskip = 1.5pt plus 1pt - \textleading = 12pt - % - \internalpagesizes{7.4in}{4.8in}% - {-.2in}{-.4in}% - {0pt}{14pt}% - {9in}{6in}% - % - \lispnarrowing = 0.25in - \tolerance = 700 - \hfuzz = 1pt - \contentsrightmargin = 0pt - \defbodyindent = .4cm -}} - -% Use @afourpaper to print on European A4 paper. -\def\afourpaper{{\globaldefs = 1 - \parskip = 3pt plus 2pt minus 1pt - \textleading = 13.2pt - % - % Double-side printing via postscript on Laserjet 4050 - % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. - % To change the settings for a different printer or situation, adjust - % \normaloffset until the front-side and back-side texts align. Then - % do the same for \bindingoffset. You can set these for testing in - % your texinfo source file like this: - % @tex - % \global\normaloffset = -6mm - % \global\bindingoffset = 10mm - % @end tex - \internalpagesizes{51\baselineskip}{160mm} - {\voffset}{\hoffset}% - {\bindingoffset}{44pt}% - {297mm}{210mm}% - % - \tolerance = 700 - \hfuzz = 1pt - \contentsrightmargin = 0pt - \defbodyindent = 5mm -}} - -% Use @afivepaper to print on European A5 paper. -% From romildo@urano.iceb.ufop.br, 2 July 2000. -% He also recommends making @example and @lisp be small. -\def\afivepaper{{\globaldefs = 1 - \parskip = 2pt plus 1pt minus 0.1pt - \textleading = 12.5pt - % - \internalpagesizes{160mm}{120mm}% - {\voffset}{\hoffset}% - {\bindingoffset}{8pt}% - {210mm}{148mm}% - % - \lispnarrowing = 0.2in - \tolerance = 800 - \hfuzz = 1.2pt - \contentsrightmargin = 0pt - \defbodyindent = 2mm - \tableindent = 12mm -}} - -% A specific text layout, 24x15cm overall, intended for A4 paper. -\def\afourlatex{{\globaldefs = 1 - \afourpaper - \internalpagesizes{237mm}{150mm}% - {\voffset}{4.6mm}% - {\bindingoffset}{7mm}% - {297mm}{210mm}% - % - % Must explicitly reset to 0 because we call \afourpaper. - \globaldefs = 0 -}} - -% Use @afourwide to print on A4 paper in landscape format. -\def\afourwide{{\globaldefs = 1 - \afourpaper - \internalpagesizes{241mm}{165mm}% - {\voffset}{-2.95mm}% - {\bindingoffset}{7mm}% - {297mm}{210mm}% - \globaldefs = 0 -}} - -% @pagesizes TEXTHEIGHT[,TEXTWIDTH] -% Perhaps we should allow setting the margins, \topskip, \parskip, -% and/or leading, also. Or perhaps we should compute them somehow. -% -\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} -\def\pagesizesyyy#1,#2,#3\finish{{% - \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi - \globaldefs = 1 - % - \parskip = 3pt plus 2pt minus 1pt - \setleading{\textleading}% - % - \dimen0 = #1 - \advance\dimen0 by \voffset - % - \dimen2 = \hsize - \advance\dimen2 by \normaloffset - % - \internalpagesizes{#1}{\hsize}% - {\voffset}{\normaloffset}% - {\bindingoffset}{44pt}% - {\dimen0}{\dimen2}% -}} - -% Set default to letter. -% -\letterpaper - - -\message{and turning on texinfo input format.} - -% Define macros to output various characters with catcode for normal text. -\catcode`\"=\other -\catcode`\~=\other -\catcode`\^=\other -\catcode`\_=\other -\catcode`\|=\other -\catcode`\<=\other -\catcode`\>=\other -\catcode`\+=\other -\catcode`\$=\other -\def\normaldoublequote{"} -\def\normaltilde{~} -\def\normalcaret{^} -\def\normalunderscore{_} -\def\normalverticalbar{|} -\def\normalless{<} -\def\normalgreater{>} -\def\normalplus{+} -\def\normaldollar{$}%$ font-lock fix - -% This macro is used to make a character print one way in \tt -% (where it can probably be output as-is), and another way in other fonts, -% where something hairier probably needs to be done. -% -% #1 is what to print if we are indeed using \tt; #2 is what to print -% otherwise. Since all the Computer Modern typewriter fonts have zero -% interword stretch (and shrink), and it is reasonable to expect all -% typewriter fonts to have this, we can check that font parameter. -% -\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} - -% Same as above, but check for italic font. Actually this also catches -% non-italic slanted fonts since it is impossible to distinguish them from -% italic fonts. But since this is only used by $ and it uses \sl anyway -% this is not a problem. -\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} - -% Turn off all special characters except @ -% (and those which the user can use as if they were ordinary). -% Most of these we simply print from the \tt font, but for some, we can -% use math or other variants that look better in normal text. - -\catcode`\"=\active -\def\activedoublequote{{\tt\char34}} -\let"=\activedoublequote -\catcode`\~=\active -\def~{{\tt\char126}} -\chardef\hat=`\^ -\catcode`\^=\active -\def^{{\tt \hat}} - -\catcode`\_=\active -\def_{\ifusingtt\normalunderscore\_} -\let\realunder=_ -% Subroutine for the previous macro. -\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } - -\catcode`\|=\active -\def|{{\tt\char124}} -\chardef \less=`\< -\catcode`\<=\active -\def<{{\tt \less}} -\chardef \gtr=`\> -\catcode`\>=\active -\def>{{\tt \gtr}} -\catcode`\+=\active -\def+{{\tt \char 43}} -\catcode`\$=\active -\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix - -% If a .fmt file is being used, characters that might appear in a file -% name cannot be active until we have parsed the command line. -% So turn them off again, and have \everyjob (or @setfilename) turn them on. -% \otherifyactive is called near the end of this file. -\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} - -% Used sometimes to turn off (effectively) the active characters even after -% parsing them. -\def\turnoffactive{% - \normalturnoffactive - \otherbackslash -} - -\catcode`\@=0 - -% \backslashcurfont outputs one backslash character in current font, -% as in \char`\\. -\global\chardef\backslashcurfont=`\\ -\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work - -% \realbackslash is an actual character `\' with catcode other, and -% \doublebackslash is two of them (for the pdf outlines). -{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} - -% In texinfo, backslash is an active character; it prints the backslash -% in fixed width font. -\catcode`\\=\active -@def@normalbackslash{{@tt@backslashcurfont}} -% On startup, @fixbackslash assigns: -% @let \ = @normalbackslash - -% \rawbackslash defines an active \ to do \backslashcurfont. -% \otherbackslash defines an active \ to be a literal `\' character with -% catcode other. -@gdef@rawbackslash{@let\=@backslashcurfont} -@gdef@otherbackslash{@let\=@realbackslash} - -% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of -% the literal character `\'. -% -@def@normalturnoffactive{% - @let\=@normalbackslash - @let"=@normaldoublequote - @let~=@normaltilde - @let^=@normalcaret - @let_=@normalunderscore - @let|=@normalverticalbar - @let<=@normalless - @let>=@normalgreater - @let+=@normalplus - @let$=@normaldollar %$ font-lock fix - @unsepspaces -} - -% Make _ and + \other characters, temporarily. -% This is canceled by @fixbackslash. -@otherifyactive - -% If a .fmt file is being used, we don't want the `\input texinfo' to show up. -% That is what \eatinput is for; after that, the `\' should revert to printing -% a backslash. -% -@gdef@eatinput input texinfo{@fixbackslash} -@global@let\ = @eatinput - -% On the other hand, perhaps the file did not have a `\input texinfo'. Then -% the first `\' in the file would cause an error. This macro tries to fix -% that, assuming it is called before the first `\' could plausibly occur. -% Also turn back on active characters that might appear in the input -% file name, in case not using a pre-dumped format. -% -@gdef@fixbackslash{% - @ifx\@eatinput @let\ = @normalbackslash @fi - @catcode`+=@active - @catcode`@_=@active -} - -% Say @foo, not \foo, in error messages. -@escapechar = `@@ - -% These look ok in all fonts, so just make them not special. -@catcode`@& = @other -@catcode`@# = @other -@catcode`@% = @other - - -@c Local variables: -@c eval: (add-hook 'write-file-hooks 'time-stamp) -@c page-delimiter: "^\\\\message" -@c time-stamp-start: "def\\\\texinfoversion{" -@c time-stamp-format: "%:y-%02m-%02d.%02H" -@c time-stamp-end: "}" -@c End: - -@c vim:sw=2: - -@ignore - arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 -@end ignore diff --git a/src/bin/m4/doc/version.texi b/src/bin/m4/doc/version.texi deleted file mode 100644 index c9d4e2fb98..0000000000 --- a/src/bin/m4/doc/version.texi +++ /dev/null @@ -1,4 +0,0 @@ -@set UPDATED 20 November 2006 -@set UPDATED-MONTH November 2006 -@set EDITION 1.4.8 -@set VERSION 1.4.8 diff --git a/src/bin/m4/lib/Jamfile b/src/bin/m4/lib/Jamfile deleted file mode 100644 index ae3f5a3401..0000000000 --- a/src/bin/m4/lib/Jamfile +++ /dev/null @@ -1,34 +0,0 @@ -SubDir HAIKU_TOP src bin m4 lib ; - -SubDirCcFlags -DHAVE_CONFIG_H ; - -SubDirSysHdrs $(SUBDIR) ; -SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; - -StaticLibrary libm4.a : - __fpending.c - allocsa.c - clean-temp.c - cloexec.c - close-stream.c - closeout.c - dup-safer.c - error.c - exitfail.c - fatal-signal.c - fd-safer.c - fopen-safer.c - gl_avltree_oset.c - gl_linkedhash_list.c - mkdtemp.c - mkstemp-safer.c - quotearg.c - strstr.c - tempname.c - tmpdir.c - verror.c - xalloc-die.c - xasprintf.c - xmalloc.c - xvasprintf.c -; diff --git a/src/bin/m4/lib/Makefile.am b/src/bin/m4/lib/Makefile.am deleted file mode 100644 index 8a0fe98fe6..0000000000 --- a/src/bin/m4/lib/Makefile.am +++ /dev/null @@ -1,558 +0,0 @@ -## DO NOT EDIT! GENERATED AUTOMATICALLY! -## Process this file with automake to produce Makefile.in. -# Copyright (C) 2004-2006 Free Software Foundation, Inc. -# -# This file is free software, distributed under the terms of the GNU -# General Public License. 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. -# Reproduce by: gnulib-tool --import --dir=. --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=. --no-libtool --macro-prefix=M4 avltree-oset binary-io clean-temp cloexec close-stream closeout config-h error fdl fopen-safer free gendocs getopt gnupload mkstemp obstack regex stdbool stdlib-safer strstr strtol unlocked-io verror xalloc xvasprintf - -AUTOMAKE_OPTIONS = 1.5 gnits - -noinst_LIBRARIES = libm4.a - -libm4_a_SOURCES = -libm4_a_LIBADD = $(M4_LIBOBJS) -libm4_a_DEPENDENCIES = $(M4_LIBOBJS) -EXTRA_libm4_a_SOURCES = -noinst_HEADERS = -EXTRA_DIST = -BUILT_SOURCES = -SUFFIXES = -MOSTLYCLEANFILES = core *.stackdump -MOSTLYCLEANDIRS = -CLEANFILES = -DISTCLEANFILES = -MAINTAINERCLEANFILES = - -AM_CPPFLAGS = - -## begin gnulib module alloca - - -EXTRA_DIST += alloca.c - -EXTRA_libm4_a_SOURCES += alloca.c - -libm4_a_LIBADD += @ALLOCA@ -libm4_a_DEPENDENCIES += @ALLOCA@ -## end gnulib module alloca - -## begin gnulib module alloca-opt - -BUILT_SOURCES += $(ALLOCA_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -alloca.h: alloca_.h - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - cat $(srcdir)/alloca_.h; \ - } > $@-t - mv -f $@-t $@ -MOSTLYCLEANFILES += alloca.h alloca.h-t - -EXTRA_DIST += alloca_.h - -## end gnulib module alloca-opt - -## begin gnulib module allocsa - -libm4_a_SOURCES += allocsa.h allocsa.c - -EXTRA_DIST += allocsa.valgrind - -## end gnulib module allocsa - -## begin gnulib module avltree-oset - -libm4_a_SOURCES += gl_avltree_oset.h gl_avltree_oset.c gl_anytree_oset.h - -## end gnulib module avltree-oset - -## begin gnulib module binary-io - -libm4_a_SOURCES += binary-io.h - -## end gnulib module binary-io - -## begin gnulib module clean-temp - -libm4_a_SOURCES += clean-temp.h clean-temp.c - -## end gnulib module clean-temp - -## begin gnulib module cloexec - - -EXTRA_DIST += cloexec.c cloexec.h - -EXTRA_libm4_a_SOURCES += cloexec.c - -## end gnulib module cloexec - -## begin gnulib module close-stream - - -EXTRA_DIST += close-stream.c close-stream.h - -EXTRA_libm4_a_SOURCES += close-stream.c - -## end gnulib module close-stream - -## begin gnulib module closeout - - -EXTRA_DIST += closeout.c closeout.h - -EXTRA_libm4_a_SOURCES += closeout.c - -## end gnulib module closeout - -## begin gnulib module error - - -EXTRA_DIST += error.c error.h - -EXTRA_libm4_a_SOURCES += error.c - -## end gnulib module error - -## begin gnulib module exit - -libm4_a_SOURCES += exit.h - -## end gnulib module exit - -## begin gnulib module exitfail - - -EXTRA_DIST += exitfail.c exitfail.h - -EXTRA_libm4_a_SOURCES += exitfail.c - -## end gnulib module exitfail - -## begin gnulib module fatal-signal - -libm4_a_SOURCES += fatal-signal.h fatal-signal.c - -## end gnulib module fatal-signal - -## begin gnulib module fopen-safer - - -EXTRA_DIST += fopen-safer.c stdio--.h stdio-safer.h - -EXTRA_libm4_a_SOURCES += fopen-safer.c - -## end gnulib module fopen-safer - -## begin gnulib module fpending - - -EXTRA_DIST += __fpending.c __fpending.h - -EXTRA_libm4_a_SOURCES += __fpending.c - -## end gnulib module fpending - -## begin gnulib module free - - -EXTRA_DIST += free.c - -EXTRA_libm4_a_SOURCES += free.c - -## end gnulib module free - -## begin gnulib module getopt - -BUILT_SOURCES += $(GETOPT_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -getopt.h: getopt_.h - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - cat $(srcdir)/getopt_.h; \ - } > $@-t - mv -f $@-t $@ -MOSTLYCLEANFILES += getopt.h getopt.h-t - -EXTRA_DIST += getopt.c getopt1.c getopt_.h getopt_int.h - -EXTRA_libm4_a_SOURCES += getopt.c getopt1.c - -## end gnulib module getopt - -## begin gnulib module gettext-h - -libm4_a_SOURCES += gettext.h - -## end gnulib module gettext-h - -## begin gnulib module linkedhash-list - -libm4_a_SOURCES += gl_linkedhash_list.h gl_linkedhash_list.c gl_anyhash_list1.h gl_anyhash_list2.h gl_anylinked_list1.h gl_anylinked_list2.h - -## end gnulib module linkedhash-list - -## begin gnulib module list - -libm4_a_SOURCES += gl_list.h gl_list.c - -## end gnulib module list - -## begin gnulib module malloc - - -EXTRA_DIST += malloc.c - -EXTRA_libm4_a_SOURCES += malloc.c - -## end gnulib module malloc - -## begin gnulib module mbchar - - -EXTRA_DIST += mbchar.c mbchar.h - -EXTRA_libm4_a_SOURCES += mbchar.c - -## end gnulib module mbchar - -## begin gnulib module mbuiter - -libm4_a_SOURCES += mbuiter.h - -## end gnulib module mbuiter - -## begin gnulib module memchr - - -EXTRA_DIST += memchr.c - -EXTRA_libm4_a_SOURCES += memchr.c - -## end gnulib module memchr - -## begin gnulib module mkdtemp - - -EXTRA_DIST += mkdtemp.c mkdtemp.h - -EXTRA_libm4_a_SOURCES += mkdtemp.c - -## end gnulib module mkdtemp - -## begin gnulib module mkstemp - - -EXTRA_DIST += mkstemp.c mkstemp.h - -EXTRA_libm4_a_SOURCES += mkstemp.c - -## end gnulib module mkstemp - -## begin gnulib module obstack - - -EXTRA_DIST += obstack.c obstack.h - -EXTRA_libm4_a_SOURCES += obstack.c - -## end gnulib module obstack - -## begin gnulib module oset - -libm4_a_SOURCES += gl_oset.h gl_oset.c - -## end gnulib module oset - -## begin gnulib module pathmax - - -EXTRA_DIST += pathmax.h - -## end gnulib module pathmax - -## begin gnulib module quotearg - - -EXTRA_DIST += quotearg.c quotearg.h - -EXTRA_libm4_a_SOURCES += quotearg.c - -## end gnulib module quotearg - -## begin gnulib module regex - - -EXTRA_DIST += regcomp.c regex.c regex.h regex_internal.c regex_internal.h regexec.c - -EXTRA_libm4_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c - -## end gnulib module regex - -## begin gnulib module sigprocmask - - -EXTRA_DIST += sigprocmask.c sigprocmask.h - -EXTRA_libm4_a_SOURCES += sigprocmask.c - -## end gnulib module sigprocmask - -## begin gnulib module size_max - -libm4_a_SOURCES += size_max.h - -## end gnulib module size_max - -## begin gnulib module stdbool - -BUILT_SOURCES += $(STDBOOL_H) - -# We need the following in order to create when the system -# doesn't have one that works. -stdbool.h: stdbool_.h - rm -f $@-t $@ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h; \ - } > $@-t - mv $@-t $@ -MOSTLYCLEANFILES += stdbool.h stdbool.h-t - -EXTRA_DIST += stdbool_.h - -## end gnulib module stdbool - -## begin gnulib module stdint - -BUILT_SOURCES += $(STDINT_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -stdint.h: stdint_.h - rm -f $@-t $@ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ - -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ - -e 's|@''ABSOLUTE_STDINT_H''@|$(ABSOLUTE_STDINT_H)|g' \ - -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ - -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ - -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ - -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ - -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ - -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ - -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ - -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ - -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ - -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ - -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ - -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ - -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ - -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ - -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ - < $(srcdir)/stdint_.h; \ - } > $@-t - mv $@-t $@ -MOSTLYCLEANFILES += stdint.h stdint.h-t - -EXTRA_DIST += stdint_.h - -## end gnulib module stdint - -## begin gnulib module stdlib-safer - - -EXTRA_DIST += mkstemp-safer.c stdlib--.h stdlib-safer.h - -EXTRA_libm4_a_SOURCES += mkstemp-safer.c - -## end gnulib module stdlib-safer - -## begin gnulib module strcase - - -EXTRA_DIST += strcase.h strcasecmp.c strncasecmp.c - -EXTRA_libm4_a_SOURCES += strcasecmp.c strncasecmp.c - -## end gnulib module strcase - -## begin gnulib module strnlen1 - -libm4_a_SOURCES += strnlen1.h strnlen1.c - -## end gnulib module strnlen1 - -## begin gnulib module strstr - - -EXTRA_DIST += strstr.c strstr.h - -EXTRA_libm4_a_SOURCES += strstr.c - -## end gnulib module strstr - -## begin gnulib module strtol - - -EXTRA_DIST += strtol.c - -EXTRA_libm4_a_SOURCES += strtol.c - -## end gnulib module strtol - -## begin gnulib module sys_stat - -BUILT_SOURCES += $(SYS_STAT_H) - -# We need the following in order to create when the system -# has one that is incomplete. -sys/stat.h: stat_.h - test -d sys || mkdir sys - rm -f $@-t $@ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''ABSOLUTE_SYS_STAT_H''@|$(ABSOLUTE_SYS_STAT_H)|g' \ - < $(srcdir)/stat_.h; \ - } > $@-t - mv $@-t $@ -MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t -MOSTLYCLEANDIRS += sys - -EXTRA_DIST += stat_.h - -## end gnulib module sys_stat - -## begin gnulib module tempname - - -EXTRA_DIST += tempname.c tempname.h - -EXTRA_libm4_a_SOURCES += tempname.c - -## end gnulib module tempname - -## begin gnulib module tmpdir - -libm4_a_SOURCES += tmpdir.h tmpdir.c - -## end gnulib module tmpdir - -## begin gnulib module unistd - -BUILT_SOURCES += $(UNISTD_H) - -# We need the following in order to create an empty placeholder for -# when the system doesn't have one. -unistd.h: - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - echo '/* Empty placeholder for $@. */'; \ - } > $@ -MOSTLYCLEANFILES += unistd.h - -## end gnulib module unistd - -## begin gnulib module unistd-safer - - -EXTRA_DIST += dup-safer.c fd-safer.c pipe-safer.c unistd--.h unistd-safer.h - -EXTRA_libm4_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c - -## end gnulib module unistd-safer - -## begin gnulib module unlocked-io - - -EXTRA_DIST += unlocked-io.h - -## end gnulib module unlocked-io - -## begin gnulib module vasnprintf - - -EXTRA_DIST += asnprintf.c printf-args.c printf-args.h printf-parse.c printf-parse.h vasnprintf.c vasnprintf.h - -EXTRA_libm4_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c - -## end gnulib module vasnprintf - -## begin gnulib module vasprintf - - -EXTRA_DIST += asprintf.c vasprintf.c vasprintf.h - -EXTRA_libm4_a_SOURCES += asprintf.c vasprintf.c - -## end gnulib module vasprintf - -## begin gnulib module verify - -libm4_a_SOURCES += verify.h - -## end gnulib module verify - -## begin gnulib module verror - -libm4_a_SOURCES += verror.h verror.c - -## end gnulib module verror - -## begin gnulib module wcwidth - -libm4_a_SOURCES += wcwidth.h - -## end gnulib module wcwidth - -## begin gnulib module xalloc - - -EXTRA_DIST += xalloc.h xmalloc.c - -EXTRA_libm4_a_SOURCES += xmalloc.c - -## end gnulib module xalloc - -## begin gnulib module xalloc-die - -libm4_a_SOURCES += xalloc-die.c - -## end gnulib module xalloc-die - -## begin gnulib module xallocsa - -libm4_a_SOURCES += xallocsa.h xallocsa.c - -## end gnulib module xallocsa - -## begin gnulib module xsize - -libm4_a_SOURCES += xsize.h - -## end gnulib module xsize - -## begin gnulib module xvasprintf - -libm4_a_SOURCES += xvasprintf.h xvasprintf.c xasprintf.c - -EXTRA_DIST += xalloc.h - -## end gnulib module xvasprintf - - -mostlyclean-local: mostlyclean-generic - @for dir in '' $(MOSTLYCLEANDIRS); do \ - if test -n "$$dir" && test -d $$dir; then \ - echo "rmdir $$dir"; rmdir $$dir; \ - fi; \ - done diff --git a/src/bin/m4/lib/Makefile.in b/src/bin/m4/lib/Makefile.in deleted file mode 100644 index 08a7af9d93..0000000000 --- a/src/bin/m4/lib/Makefile.in +++ /dev/null @@ -1,692 +0,0 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This Makefile.in 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. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# Copyright (C) 2004-2006 Free Software Foundation, Inc. -# -# This file is free software, distributed under the terms of the GNU -# General Public License. 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. -# Reproduce by: gnulib-tool --import --dir=. --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=. --no-libtool --macro-prefix=M4 avltree-oset binary-io clean-temp cloexec close-stream closeout config-h error fdl fopen-safer free gendocs getopt gnupload mkstemp obstack regex stdbool stdlib-safer strstr strtol unlocked-io verror xalloc xvasprintf - - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib -DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config.hin alloca.c -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ - $(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/allocsa.m4 \ - $(top_srcdir)/m4/cloexec.m4 $(top_srcdir)/m4/close-stream.m4 \ - $(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/config-h.m4 $(top_srcdir)/m4/eealloc.m4 \ - $(top_srcdir)/m4/eoverflow.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/fatal-signal.m4 $(top_srcdir)/m4/fpending.m4 \ - $(top_srcdir)/m4/free.m4 $(top_srcdir)/m4/getopt.m4 \ - $(top_srcdir)/m4/gl_list.m4 $(top_srcdir)/m4/gnulib-comp.m4 \ - $(top_srcdir)/m4/inline.m4 $(top_srcdir)/m4/intmax_t.m4 \ - $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/longdouble.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mbchar.m4 \ - $(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \ - $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/memchr.m4 \ - $(top_srcdir)/m4/mkdtemp.m4 $(top_srcdir)/m4/mkstemp.m4 \ - $(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/quotearg.m4 \ - $(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/sig_atomic_t.m4 \ - $(top_srcdir)/m4/signalblocking.m4 \ - $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/ssize_t.m4 \ - $(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \ - $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ - $(top_srcdir)/m4/stdio-safer.m4 \ - $(top_srcdir)/m4/stdlib-safer.m4 $(top_srcdir)/m4/strcase.m4 \ - $(top_srcdir)/m4/strstr.m4 $(top_srcdir)/m4/strtol.m4 \ - $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/tempname.m4 \ - $(top_srcdir)/m4/tmpdir.m4 $(top_srcdir)/m4/ulonglong.m4 \ - $(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \ - $(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/vasnprintf.m4 \ - $(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wcwidth.m4 $(top_srcdir)/m4/wint_t.m4 \ - $(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/m4/xvasprintf.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = -LIBRARIES = $(noinst_LIBRARIES) -AR = ar -ARFLAGS = cru -libm4_a_AR = $(AR) $(ARFLAGS) -am__DEPENDENCIES_1 = -am_libm4_a_OBJECTS = allocsa.$(OBJEXT) gl_avltree_oset.$(OBJEXT) \ - clean-temp.$(OBJEXT) fatal-signal.$(OBJEXT) \ - gl_linkedhash_list.$(OBJEXT) gl_list.$(OBJEXT) \ - gl_oset.$(OBJEXT) strnlen1.$(OBJEXT) tmpdir.$(OBJEXT) \ - verror.$(OBJEXT) xalloc-die.$(OBJEXT) xallocsa.$(OBJEXT) \ - xvasprintf.$(OBJEXT) xasprintf.$(OBJEXT) -libm4_a_OBJECTS = $(am_libm4_a_OBJECTS) -DEFAULT_INCLUDES = -I.@am__isrc@ -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libm4_a_SOURCES) $(EXTRA_libm4_a_SOURCES) -DIST_SOURCES = $(libm4_a_SOURCES) $(EXTRA_libm4_a_SOURCES) -HEADERS = $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ABSOLUTE_STDINT_H = @ABSOLUTE_STDINT_H@ -ABSOLUTE_SYS_STAT_H = @ABSOLUTE_SYS_STAT_H@ -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -ALLOCA_H = @ALLOCA_H@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ -BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ -BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ -BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ -BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EOVERFLOW = @EOVERFLOW@ -EXEEXT = @EXEEXT@ -GETOPT_H = @GETOPT_H@ -GREP = @GREP@ -HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ -HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ -HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ -HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ -HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ -HAVE_STDINT_H = @HAVE_STDINT_H@ -HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ -HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ -HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ -HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ -HAVE_WCHAR_H = @HAVE_WCHAR_H@ -HAVE__BOOL = @HAVE__BOOL@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBM4_LIBDEPS = @LIBM4_LIBDEPS@ -LIBM4_LTLIBDEPS = @LIBM4_LTLIBDEPS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -M4_LIBOBJS = @M4_LIBOBJS@ -M4_LTLIBOBJS = @M4_LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ -SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ -STDBOOL_H = @STDBOOL_H@ -STDINT_H = @STDINT_H@ -STRIP = @STRIP@ -SYS_STAT_H = @SYS_STAT_H@ -UNISTD_H = @UNISTD_H@ -VERSION = @VERSION@ -WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ -WINT_T_SUFFIX = @WINT_T_SUFFIX@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = 1.5 gnits -noinst_LIBRARIES = libm4.a -libm4_a_SOURCES = allocsa.h allocsa.c gl_avltree_oset.h \ - gl_avltree_oset.c gl_anytree_oset.h binary-io.h clean-temp.h \ - clean-temp.c exit.h fatal-signal.h fatal-signal.c gettext.h \ - gl_linkedhash_list.h gl_linkedhash_list.c gl_anyhash_list1.h \ - gl_anyhash_list2.h gl_anylinked_list1.h gl_anylinked_list2.h \ - gl_list.h gl_list.c mbuiter.h gl_oset.h gl_oset.c size_max.h \ - strnlen1.h strnlen1.c tmpdir.h tmpdir.c verify.h verror.h \ - verror.c wcwidth.h xalloc-die.c xallocsa.h xallocsa.c xsize.h \ - xvasprintf.h xvasprintf.c xasprintf.c -libm4_a_LIBADD = $(M4_LIBOBJS) @ALLOCA@ -libm4_a_DEPENDENCIES = $(M4_LIBOBJS) @ALLOCA@ -EXTRA_libm4_a_SOURCES = alloca.c cloexec.c close-stream.c closeout.c \ - error.c exitfail.c fopen-safer.c __fpending.c free.c getopt.c \ - getopt1.c malloc.c mbchar.c memchr.c mkdtemp.c mkstemp.c \ - obstack.c quotearg.c regcomp.c regex.c regex_internal.c \ - regexec.c sigprocmask.c mkstemp-safer.c strcasecmp.c \ - strncasecmp.c strstr.c strtol.c tempname.c dup-safer.c \ - fd-safer.c pipe-safer.c asnprintf.c printf-args.c \ - printf-parse.c vasnprintf.c asprintf.c vasprintf.c xmalloc.c -noinst_HEADERS = -EXTRA_DIST = alloca.c alloca_.h allocsa.valgrind cloexec.c cloexec.h \ - close-stream.c close-stream.h closeout.c closeout.h error.c \ - error.h exitfail.c exitfail.h fopen-safer.c stdio--.h \ - stdio-safer.h __fpending.c __fpending.h free.c getopt.c \ - getopt1.c getopt_.h getopt_int.h malloc.c mbchar.c mbchar.h \ - memchr.c mkdtemp.c mkdtemp.h mkstemp.c mkstemp.h obstack.c \ - obstack.h pathmax.h quotearg.c quotearg.h regcomp.c regex.c \ - regex.h regex_internal.c regex_internal.h regexec.c \ - sigprocmask.c sigprocmask.h stdbool_.h stdint_.h \ - mkstemp-safer.c stdlib--.h stdlib-safer.h strcase.h \ - strcasecmp.c strncasecmp.c strstr.c strstr.h strtol.c stat_.h \ - tempname.c tempname.h dup-safer.c fd-safer.c pipe-safer.c \ - unistd--.h unistd-safer.h unlocked-io.h asnprintf.c \ - printf-args.c printf-args.h printf-parse.c printf-parse.h \ - vasnprintf.c vasnprintf.h asprintf.c vasprintf.c vasprintf.h \ - xalloc.h xmalloc.c xalloc.h -BUILT_SOURCES = $(ALLOCA_H) $(GETOPT_H) $(STDBOOL_H) $(STDINT_H) \ - $(SYS_STAT_H) $(UNISTD_H) -SUFFIXES = -MOSTLYCLEANFILES = core *.stackdump alloca.h alloca.h-t getopt.h \ - getopt.h-t stdbool.h stdbool.h-t stdint.h stdint.h-t \ - sys/stat.h sys/stat.h-t unistd.h -MOSTLYCLEANDIRS = sys -CLEANFILES = -DISTCLEANFILES = -MAINTAINERCLEANFILES = -AM_CPPFLAGS = -all: $(BUILT_SOURCES) config.h - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits lib/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnits lib/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ - else :; fi - -stamp-h1: $(srcdir)/config.hin $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status lib/config.h -$(srcdir)/config.hin: $(am__configure_deps) - cd $(top_srcdir) && $(AUTOHEADER) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f config.h stamp-h1 - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libm4.a: $(libm4_a_OBJECTS) $(libm4_a_DEPENDENCIES) - -rm -f libm4.a - $(libm4_a_AR) libm4.a $(libm4_a_OBJECTS) $(libm4_a_LIBADD) - $(RANLIB) libm4.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/__fpending.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloca.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/allocsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asnprintf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asprintf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clean-temp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cloexec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/close-stream.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closeout.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup-safer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exitfail.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fatal-signal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-safer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fopen-safer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/free.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_avltree_oset.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_linkedhash_list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_oset.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbchar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memchr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkdtemp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkstemp-safer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkstemp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obstack.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipe-safer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf-args.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf-parse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quotearg.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_internal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigprocmask.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strncasecmp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnlen1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strstr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strtol.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tempname.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tmpdir.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vasnprintf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vasprintf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verror.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xalloc-die.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xallocsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xasprintf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmalloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvasprintf.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) config.hin $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config.hin $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) config.hin $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config.hin $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LIBRARIES) $(HEADERS) config.h -installdirs: -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -rf $(DEPDIR) ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-hdr distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf $(DEPDIR) ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-local - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES ctags distclean distclean-compile \ - distclean-generic distclean-hdr distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-local pdf pdf-am ps ps-am tags \ - uninstall uninstall-am - - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -alloca.h: alloca_.h - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - cat $(srcdir)/alloca_.h; \ - } > $@-t - mv -f $@-t $@ - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -getopt.h: getopt_.h - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - cat $(srcdir)/getopt_.h; \ - } > $@-t - mv -f $@-t $@ - -# We need the following in order to create when the system -# doesn't have one that works. -stdbool.h: stdbool_.h - rm -f $@-t $@ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h; \ - } > $@-t - mv $@-t $@ - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -stdint.h: stdint_.h - rm -f $@-t $@ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ - -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ - -e 's|@''ABSOLUTE_STDINT_H''@|$(ABSOLUTE_STDINT_H)|g' \ - -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ - -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ - -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ - -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ - -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ - -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ - -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ - -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ - -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ - -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ - -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ - -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ - -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ - -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ - -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ - < $(srcdir)/stdint_.h; \ - } > $@-t - mv $@-t $@ - -# We need the following in order to create when the system -# has one that is incomplete. -sys/stat.h: stat_.h - test -d sys || mkdir sys - rm -f $@-t $@ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''ABSOLUTE_SYS_STAT_H''@|$(ABSOLUTE_SYS_STAT_H)|g' \ - < $(srcdir)/stat_.h; \ - } > $@-t - mv $@-t $@ - -# We need the following in order to create an empty placeholder for -# when the system doesn't have one. -unistd.h: - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - echo '/* Empty placeholder for $@. */'; \ - } > $@ - -mostlyclean-local: mostlyclean-generic - @for dir in '' $(MOSTLYCLEANDIRS); do \ - if test -n "$$dir" && test -d $$dir; then \ - echo "rmdir $$dir"; rmdir $$dir; \ - fi; \ - done -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/bin/m4/lib/__fpending.c b/src/bin/m4/lib/__fpending.c deleted file mode 100644 index 221aee69de..0000000000 --- a/src/bin/m4/lib/__fpending.c +++ /dev/null @@ -1,30 +0,0 @@ -/* __fpending.c -- return the number of pending output bytes on a stream - Copyright (C) 2000, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#include - -#include "__fpending.h" - -/* Return the number of pending (aka buffered, unflushed) - bytes on the stream, FP, that is open for writing. */ -size_t -__fpending (FILE *fp) -{ - return PENDING_OUTPUT_N_BYTES; -} diff --git a/src/bin/m4/lib/__fpending.h b/src/bin/m4/lib/__fpending.h deleted file mode 100644 index 8a8aabcc22..0000000000 --- a/src/bin/m4/lib/__fpending.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Declare __fpending. - - Copyright (C) 2000, 2003, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Written by Jim Meyering. */ - -#include -#include - -#ifndef HAVE_DECL___FPENDING -"this configure-time declaration test was not run" -#endif - -#if HAVE_DECL___FPENDING -# if HAVE_STDIO_EXT_H -# include -# endif -#else -size_t __fpending (FILE *); -#endif diff --git a/src/bin/m4/lib/alloca.c b/src/bin/m4/lib/alloca.c deleted file mode 100644 index 3a1f4e273a..0000000000 --- a/src/bin/m4/lib/alloca.c +++ /dev/null @@ -1,489 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#include - -#include - -#include -#include - -#ifdef emacs -# include "lisp.h" -# include "blockinput.h" -# ifdef EMACS_FREE -# undef free -# define free EMACS_FREE -# endif -#else -# define memory_full() abort () -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -# ifndef alloca - -# ifdef emacs -# ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -# ifndef STACK_DIRECTION -you -lose --- must know STACK_DIRECTION at compile-time -/* Using #error here is not wise since this file should work for - old and obscure compilers. */ -# endif /* STACK_DIRECTION undefined */ -# endif /* static */ -# endif /* emacs */ - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -# else -# define ADDRESS_FUNCTION(arg) &(arg) -# endif - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -# ifndef STACK_DIRECTION -# define STACK_DIRECTION 0 /* Direction unknown. */ -# endif - -# if STACK_DIRECTION != 0 - -# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -# else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -# define STACK_DIR stack_dir - -static void -find_stack_direction (void) -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -# endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -# ifndef ALIGN_SIZE -# define ALIGN_SIZE sizeof(double) -# endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -void * -alloca (size_t size) -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -# if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -# endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -# ifdef emacs - BLOCK_INPUT; -# endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free (hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -# ifdef emacs - UNBLOCK_INPUT; -# endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - /* Address of header. */ - register header *new; - - size_t combined_size = sizeof (header) + size; - if (combined_size < sizeof (header)) - memory_full (); - - new = malloc (combined_size); - - if (! new) - memory_full (); - - new->h.next = last_alloca_header; - new->h.deep = depth; - - last_alloca_header = new; - - /* User storage begins just after header. */ - - return (void *) (new + 1); - } -} - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) - -# ifdef DEBUG_I00AFUNC -# include -# endif - -# ifndef CRAY_STACK -# define CRAY_STACK -# ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -# else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -# endif /* CRAY2 */ -# endif /* not CRAY_STACK */ - -# ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -# else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -# endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -# endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -# endif /* not CRAY2 */ -# endif /* CRAY */ - -# endif /* no alloca */ -#endif /* not GCC version 2 */ diff --git a/src/bin/m4/lib/alloca_.h b/src/bin/m4/lib/alloca_.h deleted file mode 100644 index dd0b3e98f5..0000000000 --- a/src/bin/m4/lib/alloca_.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Memory allocation on the stack. - - Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004, 2006 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 2, 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - USA. */ - -/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H - means there is a real alloca function. */ -#ifndef _GNULIB_ALLOCA_H -# define _GNULIB_ALLOCA_H - -/* alloca (N) returns a pointer to N bytes of memory - allocated on the stack, which will last until the function returns. - Use of alloca should be avoided: - - inside arguments of function calls - undefined behaviour, - - in inline functions - the allocation may actually last until the - calling function returns, - - for huge N (say, N >= 65536) - you never know how large (or small) - the stack is, and when the stack cannot fulfill the memory allocation - request, the program just crashes. - */ - -#ifndef alloca -# ifdef __GNUC__ -# define alloca __builtin_alloca -# elif defined _AIX -# define alloca __alloca -# elif defined _MSC_VER -# include -# define alloca _alloca -# else -# include -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -# endif -#endif - -#endif /* _GNULIB_ALLOCA_H */ diff --git a/src/bin/m4/lib/allocsa.c b/src/bin/m4/lib/allocsa.c deleted file mode 100644 index 97652e6889..0000000000 --- a/src/bin/m4/lib/allocsa.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Safe automatic memory allocation. - Copyright (C) 2003, 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2003. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "allocsa.h" - -/* The speed critical point in this file is freesa() applied to an alloca() - result: it must be fast, to match the speed of alloca(). The speed of - mallocsa() and freesa() in the other case are not critical, because they - are only invoked for big memory sizes. */ - -#if HAVE_ALLOCA - -/* Store the mallocsa() results in a hash table. This is needed to reliably - distinguish a mallocsa() result and an alloca() result. - - Although it is possible that the same pointer is returned by alloca() and - by mallocsa() at different times in the same application, it does not lead - to a bug in freesa(), because: - - Before a pointer returned by alloca() can point into malloc()ed memory, - the function must return, and once this has happened the programmer must - not call freesa() on it anyway. - - Before a pointer returned by mallocsa() can point into the stack, it - must be freed. The only function that can free it is freesa(), and - when freesa() frees it, it also removes it from the hash table. */ - -#define MAGIC_NUMBER 0x1415fb4a -#define MAGIC_SIZE sizeof (int) -/* This is how the header info would look like without any alignment - considerations. */ -struct preliminary_header { void *next; char room[MAGIC_SIZE]; }; -/* But the header's size must be a multiple of sa_alignment_max. */ -#define HEADER_SIZE \ - (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max) -struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; }; -/* Verify that HEADER_SIZE == sizeof (struct header). */ -typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1]; -/* We make the hash table quite big, so that during lookups the probability - of empty hash buckets is quite high. There is no need to make the hash - table resizable, because when the hash table gets filled so much that the - lookup becomes slow, it means that the application has memory leaks. */ -#define HASH_TABLE_SIZE 257 -static void * mallocsa_results[HASH_TABLE_SIZE]; - -#endif - -void * -mallocsa (size_t n) -{ -#if HAVE_ALLOCA - /* Allocate one more word, that serves as an indicator for malloc()ed - memory, so that freesa() of an alloca() result is fast. */ - size_t nplus = n + HEADER_SIZE; - - if (nplus >= n) - { - char *p = (char *) malloc (nplus); - - if (p != NULL) - { - size_t slot; - - p += HEADER_SIZE; - - /* Put a magic number into the indicator word. */ - ((int *) p)[-1] = MAGIC_NUMBER; - - /* Enter p into the hash table. */ - slot = (unsigned long) p % HASH_TABLE_SIZE; - ((struct header *) (p - HEADER_SIZE))->next = mallocsa_results[slot]; - mallocsa_results[slot] = p; - - return p; - } - } - /* Out of memory. */ - return NULL; -#else -# if !MALLOC_0_IS_NONNULL - if (n == 0) - n = 1; -# endif - return malloc (n); -#endif -} - -#if HAVE_ALLOCA -void -freesa (void *p) -{ - /* mallocsa() may have returned NULL. */ - if (p != NULL) - { - /* Attempt to quickly distinguish the mallocsa() result - which has - a magic indicator word - and the alloca() result - which has an - uninitialized indicator word. It is for this test that sa_increment - additional bytes are allocated in the alloca() case. */ - if (((int *) p)[-1] == MAGIC_NUMBER) - { - /* Looks like a mallocsa() result. To see whether it really is one, - perform a lookup in the hash table. */ - size_t slot = (unsigned long) p % HASH_TABLE_SIZE; - void **chain = &mallocsa_results[slot]; - for (; *chain != NULL;) - { - if (*chain == p) - { - /* Found it. Remove it from the hash table and free it. */ - char *p_begin = (char *) p - HEADER_SIZE; - *chain = ((struct header *) p_begin)->next; - free (p_begin); - return; - } - chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next; - } - } - /* At this point, we know it was not a mallocsa() result. */ - } -} -#endif diff --git a/src/bin/m4/lib/allocsa.h b/src/bin/m4/lib/allocsa.h deleted file mode 100644 index 0fd46a8e6a..0000000000 --- a/src/bin/m4/lib/allocsa.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Safe automatic memory allocation. - Copyright (C) 2003-2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2003. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _ALLOCSA_H -#define _ALLOCSA_H - -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call - alloca(N); otherwise it returns NULL. It either returns N bytes of - memory allocated on the stack, that lasts until the function returns, - or NULL. - Use of safe_alloca should be avoided: - - inside arguments of function calls - undefined behaviour, - - in inline functions - the allocation may actually last until the - calling function returns. -*/ -#if HAVE_ALLOCA -/* The OS usually guarantees only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - allocate anything larger than 4096 bytes. Also care for the possibility - of a few compiler-allocated temporary stack slots. - This must be a macro, not an inline function. */ -# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL) -#else -# define safe_alloca(N) ((N), NULL) -#endif - -/* allocsa(N) is a safe variant of alloca(N). It allocates N bytes of - memory allocated on the stack, that must be freed using freesa() before - the function returns. Upon failure, it returns NULL. */ -#if HAVE_ALLOCA -# define allocsa(N) \ - ((N) < 4032 - sa_increment \ - ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \ - : mallocsa (N)) -#else -# define allocsa(N) \ - mallocsa (N) -#endif -extern void * mallocsa (size_t n); - -/* Free a block of memory allocated through allocsa(). */ -#if HAVE_ALLOCA -extern void freesa (void *p); -#else -# define freesa free -#endif - -/* Maybe we should also define a variant - nallocsa (size_t n, size_t s) - behaves like allocsa (n * s) - If this would be useful in your application. please speak up. */ - - -#ifdef __cplusplus -} -#endif - - -/* ------------------- Auxiliary, non-public definitions ------------------- */ - -/* Determine the alignment of a type at compile time. */ -#if defined __GNUC__ -# define sa_alignof __alignof__ -#elif defined __cplusplus - template struct sa_alignof_helper { char __slot1; type __slot2; }; -# define sa_alignof(type) offsetof (sa_alignof_helper, __slot2) -#elif defined __hpux - /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof - values. */ -# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) -#elif defined _AIX - /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof - values. */ -# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) -#else -# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) -#endif - -enum -{ -/* The desired alignment of memory allocations is the maximum alignment - among all elementary types. */ - sa_alignment_long = sa_alignof (long), - sa_alignment_double = sa_alignof (double), -#ifdef HAVE_LONG_LONG_INT - sa_alignment_longlong = sa_alignof (long long), -#endif -#ifdef HAVE_LONG_DOUBLE - sa_alignment_longdouble = sa_alignof (long double), -#endif - sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) -#ifdef HAVE_LONG_LONG_INT - | (sa_alignment_longlong - 1) -#endif -#ifdef HAVE_LONG_DOUBLE - | (sa_alignment_longdouble - 1) -#endif - ) + 1, -/* The increment that guarantees room for a magic word must be >= sizeof (int) - and a multiple of sa_alignment_max. */ - sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max -}; - -#endif /* _ALLOCSA_H */ diff --git a/src/bin/m4/lib/allocsa.valgrind b/src/bin/m4/lib/allocsa.valgrind deleted file mode 100644 index f4c77d6861..0000000000 --- a/src/bin/m4/lib/allocsa.valgrind +++ /dev/null @@ -1,7 +0,0 @@ -# Suppress a valgrind message about use of uninitialized memory in freesa(). -# This use is OK because it provides only a speedup. -{ - freesa - Memcheck:Cond - fun:freesa -} diff --git a/src/bin/m4/lib/asnprintf.c b/src/bin/m4/lib/asnprintf.c deleted file mode 100644 index 26c3988b01..0000000000 --- a/src/bin/m4/lib/asnprintf.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 1999, 2002, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "vasnprintf.h" - -#include - -char * -asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) -{ - va_list args; - char *result; - - va_start (args, format); - result = vasnprintf (resultbuf, lengthp, format, args); - va_end (args); - return result; -} diff --git a/src/bin/m4/lib/asprintf.c b/src/bin/m4/lib/asprintf.c deleted file mode 100644 index 29ac6cf2d1..0000000000 --- a/src/bin/m4/lib/asprintf.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 1999, 2002, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "vasprintf.h" - -#include - -int -asprintf (char **resultp, const char *format, ...) -{ - va_list args; - int result; - - va_start (args, format); - result = vasprintf (resultp, format, args); - va_end (args); - return result; -} diff --git a/src/bin/m4/lib/binary-io.h b/src/bin/m4/lib/binary-io.h deleted file mode 100644 index 07b633cfa4..0000000000 --- a/src/bin/m4/lib/binary-io.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Binary mode I/O. - Copyright (C) 2001, 2003, 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _BINARY_H -#define _BINARY_H - -/* For systems that distinguish between text and binary I/O. - O_BINARY is usually declared in . */ -#include - -/* The MSVC7 doesn't like to be included after '#define fileno ...', - so we include it here first. */ -#include - -#if !defined O_BINARY && defined _O_BINARY - /* For MSC-compatible compilers. */ -# define O_BINARY _O_BINARY -# define O_TEXT _O_TEXT -#endif -#if (defined(__BEOS__) || defined(__HAIKU__)) - /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ -# undef O_BINARY -# undef O_TEXT -#endif -#if O_BINARY -# if !(defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__) -# define setmode _setmode -# undef fileno -# define fileno _fileno -# endif -# if defined __DJGPP__ || defined __CYGWIN__ -# include /* declares setmode() */ -# endif -# ifdef __DJGPP__ -# include /* declares isatty() */ -# /* Avoid putting stdin/stdout in binary mode if it is connected to the -# console, because that would make it impossible for the user to -# interrupt the program through Ctrl-C or Ctrl-Break. */ -# define SET_BINARY(fd) (!isatty (fd) ? (setmode (fd, O_BINARY), 0) : 0) -# else -# define SET_BINARY(fd) setmode (fd, O_BINARY) -# endif -#else - /* On reasonable systems, binary I/O is the default. */ -# undef O_BINARY -# define O_BINARY 0 -# define SET_BINARY(fd) /* nothing */ -#endif - -#endif /* _BINARY_H */ diff --git a/src/bin/m4/lib/clean-temp.c b/src/bin/m4/lib/clean-temp.c deleted file mode 100644 index aa82974a1e..0000000000 --- a/src/bin/m4/lib/clean-temp.c +++ /dev/null @@ -1,715 +0,0 @@ -/* Temporary directories and temporary files with automatic cleanup. - Copyright (C) 2001, 2003, 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - - -#include - -/* Specification. */ -#include "clean-temp.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "error.h" -#include "fatal-signal.h" -#include "pathmax.h" -#include "tmpdir.h" -#include "mkdtemp.h" -#include "xalloc.h" -#include "xallocsa.h" -#include "gl_linkedhash_list.h" -#include "gettext.h" -#if GNULIB_FWRITEERROR -# include "fwriteerror.h" -#endif -#if GNULIB_CLOSE_STREAM -# include "close-stream.h" -#endif -#if GNULIB_FCNTL_SAFER -# include "fcntl--.h" -#endif -#if GNULIB_FOPEN_SAFER -# include "stdio--.h" -#endif - -#define _(str) gettext (str) - -/* GNU Hurd doesn't have PATH_MAX. */ -#ifndef PATH_MAX -# ifdef MAXPATHLEN -# define PATH_MAX MAXPATHLEN -# else -# define PATH_MAX 1024 -# endif -#endif - -#ifndef uintptr_t -# define uintptr_t unsigned long -#endif - - -/* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5)) - ensure that while constructing or modifying the data structures, the field - values are written to memory in the order of the C statements. So the - signal handler can rely on these field values to be up to date. */ - - -/* Registry for a single temporary directory. - 'struct temp_dir' from the public header file overlaps with this. */ -struct tempdir -{ - /* The absolute pathname of the directory. */ - char * volatile dirname; - /* Whether errors during explicit cleanup are reported to standard error. */ - bool cleanup_verbose; - /* Absolute pathnames of subdirectories. */ - gl_list_t /* */ volatile subdirs; - /* Absolute pathnames of files. */ - gl_list_t /* */ volatile files; -}; - -/* List of all temporary directories. */ -static struct -{ - struct tempdir * volatile * volatile tempdir_list; - size_t volatile tempdir_count; - size_t tempdir_allocated; -} cleanup_list /* = { NULL, 0, 0 } */; - -/* List of all open file descriptors to temporary files. */ -static gl_list_t /* */ volatile descriptors; - - -/* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH. - Why? We need a data structure that - - 1) Can contain an arbitrary number of 'char *' values. The strings - are compared via strcmp, not pointer comparison. - 2) Has insertion and deletion operations that are fast: ideally O(1), - or possibly O(log n). This is important for GNU sort, which may - create a large number of temporary files. - 3) Allows iteration through all elements from within a signal handler. - 4) May or may not allow duplicates. It doesn't matter here, since - any file or subdir can only be removed once. - - Criterion 1) would allow any gl_list_t or gl_oset_t implementation. - - Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or - GL_TREE_OSET. - - Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET. - Namely, iteration through the elements of a binary tree requires access - to many ->left, ->right, ->parent pointers. However, the rebalancing - code for insertion and deletion in an AVL or red-black tree is so - complicated that we cannot assume that >left, ->right, ->parent pointers - are in a consistent state throughout these operations. Therefore, to - avoid a crash in the signal handler, all destructive operations to the - lists would have to be protected by a - block_fatal_signals (); - ... - unblock_fatal_signals (); - pair. Which causes extra system calls. - - Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST, - if they were not already excluded. Namely, these implementations use - xrealloc(), leaving a time window in which in the list->elements pointer - points to already deallocated memory. To avoid a crash in the signal - handler at such a moment, all destructive operations would have to - protected by block/unblock_fatal_signals (), in this case too. - - A list of type GL_LINKEDHASH_LIST without duplicates fulfills all - requirements: - 2) Insertion and deletion are O(1) on average. - 3) The gl_list_iterator, gl_list_iterator_next implementations do - not trigger memory allocations, nor other system calls, and are - therefore safe to be called from a signal handler. - Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation - of the destructive functions ensures that the list structure is - safe to be traversed at any moment, even when interrupted by an - asynchronous signal. - */ - -/* String equality and hash code functions used by the lists. */ - -static bool -string_equals (const void *x1, const void *x2) -{ - const char *s1 = (const char *) x1; - const char *s2 = (const char *) x2; - return strcmp (s1, s2) == 0; -} - -#define SIZE_BITS (sizeof (size_t) * CHAR_BIT) - -/* A hash function for NUL-terminated char* strings using - the method described by Bruno Haible. - See http://www.haible.de/bruno/hashfunc.html. */ -static size_t -string_hash (const void *x) -{ - const char *s = (const char *) x; - size_t h = 0; - - for (; *s; s++) - h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); - - return h; -} - - -/* The signal handler. It gets called asynchronously. */ -static void -cleanup () -{ - size_t i; - - /* First close all file descriptors to temporary files. */ - { - gl_list_t fds = descriptors; - - if (fds != NULL) - { - gl_list_iterator_t iter; - const void *element; - - iter = gl_list_iterator (fds); - while (gl_list_iterator_next (&iter, &element, NULL)) - { - int fd = (int) (uintptr_t) element; - close (fd); - } - gl_list_iterator_free (&iter); - } - } - - for (i = 0; i < cleanup_list.tempdir_count; i++) - { - struct tempdir *dir = cleanup_list.tempdir_list[i]; - - if (dir != NULL) - { - gl_list_iterator_t iter; - const void *element; - - /* First cleanup the files in the subdirectories. */ - iter = gl_list_iterator (dir->files); - while (gl_list_iterator_next (&iter, &element, NULL)) - { - const char *file = (const char *) element; - unlink (file); - } - gl_list_iterator_free (&iter); - - /* Then cleanup the subdirectories. */ - iter = gl_list_iterator (dir->subdirs); - while (gl_list_iterator_next (&iter, &element, NULL)) - { - const char *subdir = (const char *) element; - rmdir (subdir); - } - gl_list_iterator_free (&iter); - - /* Then cleanup the temporary directory itself. */ - rmdir (dir->dirname); - } - } -} - -/* Create a temporary directory. - PREFIX is used as a prefix for the name of the temporary directory. It - should be short and still give an indication about the program. - PARENTDIR can be used to specify the parent directory; if NULL, a default - parent directory is used (either $TMPDIR or /tmp or similar). - CLEANUP_VERBOSE determines whether errors during explicit cleanup are - reported to standard error. - Return a fresh 'struct temp_dir' on success. Upon error, an error message - is shown and NULL is returned. */ -struct temp_dir * -create_temp_dir (const char *prefix, const char *parentdir, - bool cleanup_verbose) -{ - struct tempdir * volatile *tmpdirp = NULL; - struct tempdir *tmpdir; - size_t i; - char *xtemplate; - char *tmpdirname; - - /* See whether it can take the slot of an earlier temporary directory - already cleaned up. */ - for (i = 0; i < cleanup_list.tempdir_count; i++) - if (cleanup_list.tempdir_list[i] == NULL) - { - tmpdirp = &cleanup_list.tempdir_list[i]; - break; - } - if (tmpdirp == NULL) - { - /* See whether the array needs to be extended. */ - if (cleanup_list.tempdir_count == cleanup_list.tempdir_allocated) - { - /* Note that we cannot use xrealloc(), because then the cleanup() - function could access an already deallocated array. */ - struct tempdir * volatile *old_array = cleanup_list.tempdir_list; - size_t old_allocated = cleanup_list.tempdir_allocated; - size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1; - struct tempdir * volatile *new_array = - XNMALLOC (new_allocated, struct tempdir * volatile); - - if (old_allocated == 0) - /* First use of this facility. Register the cleanup handler. */ - at_fatal_signal (&cleanup); - else - { - /* Don't use memcpy() here, because memcpy takes non-volatile - arguments and is therefore not guaranteed to complete all - memory stores before the next statement. */ - size_t k; - - for (k = 0; k < old_allocated; k++) - new_array[k] = old_array[k]; - } - - cleanup_list.tempdir_list = new_array; - cleanup_list.tempdir_allocated = new_allocated; - - /* Now we can free the old array. */ - if (old_array != NULL) - free ((struct tempdir **) old_array); - } - - tmpdirp = &cleanup_list.tempdir_list[cleanup_list.tempdir_count]; - /* Initialize *tmpdirp before incrementing tempdir_count, so that - cleanup() will skip this entry before it is fully initialized. */ - *tmpdirp = NULL; - cleanup_list.tempdir_count++; - } - - /* Initialize a 'struct tempdir'. */ - tmpdir = XMALLOC (struct tempdir); - tmpdir->dirname = NULL; - tmpdir->cleanup_verbose = cleanup_verbose; - tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST, - string_equals, string_hash, false); - tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST, - string_equals, string_hash, false); - - /* Create the temporary directory. */ - xtemplate = (char *) xallocsa (PATH_MAX); - if (path_search (xtemplate, PATH_MAX, parentdir, prefix, parentdir == NULL)) - { - error (0, errno, - _("cannot find a temporary directory, try setting $TMPDIR")); - goto quit; - } - block_fatal_signals (); - tmpdirname = mkdtemp (xtemplate); - if (tmpdirname != NULL) - { - tmpdir->dirname = tmpdirname; - *tmpdirp = tmpdir; - } - unblock_fatal_signals (); - if (tmpdirname == NULL) - { - error (0, errno, - _("cannot create a temporary directory using template \"%s\""), - xtemplate); - goto quit; - } - /* Replace tmpdir->dirname with a copy that has indefinite extent. - We cannot do this inside the block_fatal_signals/unblock_fatal_signals - block because then the cleanup handler would not remove the directory - if xstrdup fails. */ - tmpdir->dirname = xstrdup (tmpdirname); - freesa (xtemplate); - return (struct temp_dir *) tmpdir; - - quit: - freesa (xtemplate); - return NULL; -} - -/* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that - needs to be removed before DIR can be removed. - Should be called before the file ABSOLUTE_FILE_NAME is created. */ -void -register_temp_file (struct temp_dir *dir, - const char *absolute_file_name) -{ - struct tempdir *tmpdir = (struct tempdir *)dir; - - /* Add absolute_file_name to tmpdir->files, without duplicates. */ - if (gl_list_search (tmpdir->files, absolute_file_name) == NULL) - gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name)); -} - -/* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that - needs to be removed before DIR can be removed. - Should be called when the file ABSOLUTE_FILE_NAME could not be created. */ -void -unregister_temp_file (struct temp_dir *dir, - const char *absolute_file_name) -{ - struct tempdir *tmpdir = (struct tempdir *)dir; - gl_list_t list = tmpdir->files; - gl_list_node_t node; - - node = gl_list_search (list, absolute_file_name); - if (node != NULL) - { - char *old_string = (char *) gl_list_node_value (list, node); - - gl_list_remove_node (list, node); - free (old_string); - } -} - -/* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, - that needs to be removed before DIR can be removed. - Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */ -void -register_temp_subdir (struct temp_dir *dir, - const char *absolute_dir_name) -{ - struct tempdir *tmpdir = (struct tempdir *)dir; - - /* Add absolute_dir_name to tmpdir->subdirs, without duplicates. */ - if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL) - gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name)); -} - -/* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, - that needs to be removed before DIR can be removed. - Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be - created. */ -void -unregister_temp_subdir (struct temp_dir *dir, - const char *absolute_dir_name) -{ - struct tempdir *tmpdir = (struct tempdir *)dir; - gl_list_t list = tmpdir->subdirs; - gl_list_node_t node; - - node = gl_list_search (list, absolute_dir_name); - if (node != NULL) - { - char *old_string = (char *) gl_list_node_value (list, node); - - gl_list_remove_node (list, node); - free (old_string); - } -} - -/* Remove a file, with optional error message. - Return 0 upon success, or -1 if there was some problem. */ -static int -do_unlink (struct temp_dir *dir, const char *absolute_file_name) -{ - if (unlink (absolute_file_name) < 0 && dir->cleanup_verbose - && errno != ENOENT) - { - error (0, errno, _("cannot remove temporary file %s"), absolute_file_name); - return -1; - } - return 0; -} - -/* Remove a directory, with optional error message. - Return 0 upon success, or -1 if there was some problem. */ -static int -do_rmdir (struct temp_dir *dir, const char *absolute_dir_name) -{ - if (rmdir (absolute_dir_name) < 0 && dir->cleanup_verbose - && errno != ENOENT) - { - error (0, errno, - _("cannot remove temporary directory %s"), absolute_dir_name); - return -1; - } - return 0; -} - -/* Remove the given ABSOLUTE_FILE_NAME and unregister it. - Return 0 upon success, or -1 if there was some problem. */ -int -cleanup_temp_file (struct temp_dir *dir, - const char *absolute_file_name) -{ - int err; - - err = do_unlink (dir, absolute_file_name); - unregister_temp_file (dir, absolute_file_name); - - return err; -} - -/* Remove the given ABSOLUTE_DIR_NAME and unregister it. - Return 0 upon success, or -1 if there was some problem. */ -int -cleanup_temp_subdir (struct temp_dir *dir, - const char *absolute_dir_name) -{ - int err; - - err = do_rmdir (dir, absolute_dir_name); - unregister_temp_subdir (dir, absolute_dir_name); - - return err; -} - -/* Remove all registered files and subdirectories inside DIR. - Return 0 upon success, or -1 if there was some problem. */ -int -cleanup_temp_dir_contents (struct temp_dir *dir) -{ - struct tempdir *tmpdir = (struct tempdir *)dir; - int err = 0; - gl_list_t list; - gl_list_iterator_t iter; - const void *element; - gl_list_node_t node; - - /* First cleanup the files in the subdirectories. */ - list = tmpdir->files; - iter = gl_list_iterator (list); - while (gl_list_iterator_next (&iter, &element, &node)) - { - char *file = (char *) element; - - err |= do_unlink (dir, file); - gl_list_remove_node (list, node); - /* Now only we can free file. */ - free (file); - } - gl_list_iterator_free (&iter); - - /* Then cleanup the subdirectories. */ - list = tmpdir->subdirs; - iter = gl_list_iterator (list); - while (gl_list_iterator_next (&iter, &element, &node)) - { - char *subdir = (char *) element; - - err |= do_rmdir (dir, subdir); - gl_list_remove_node (list, node); - /* Now only we can free subdir. */ - free (subdir); - } - gl_list_iterator_free (&iter); - - return err; -} - -/* Remove all registered files and subdirectories inside DIR and DIR itself. - DIR cannot be used any more after this call. - Return 0 upon success, or -1 if there was some problem. */ -int -cleanup_temp_dir (struct temp_dir *dir) -{ - struct tempdir *tmpdir = (struct tempdir *)dir; - int err = 0; - size_t i; - - err |= cleanup_temp_dir_contents (dir); - err |= do_rmdir (dir, tmpdir->dirname); - - for (i = 0; i < cleanup_list.tempdir_count; i++) - if (cleanup_list.tempdir_list[i] == tmpdir) - { - /* Remove cleanup_list.tempdir_list[i]. */ - if (i + 1 == cleanup_list.tempdir_count) - { - while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL) - i--; - cleanup_list.tempdir_count = i; - } - else - cleanup_list.tempdir_list[i] = NULL; - /* Now only we can free the tmpdir->dirname and tmpdir itself. */ - free (tmpdir->dirname); - free (tmpdir); - return err; - } - - /* The user passed an invalid DIR argument. */ - abort (); -} - - -/* Register a file descriptor to be closed. */ -static void -register_fd (int fd) -{ - if (descriptors == NULL) - descriptors = gl_list_create_empty (GL_LINKEDHASH_LIST, NULL, NULL, false); - gl_list_add_first (descriptors, (void *) (uintptr_t) fd); -} - -/* Unregister a file descriptor to be closed. */ -static void -unregister_fd (int fd) -{ - gl_list_t fds = descriptors; - gl_list_node_t node; - - if (fds == NULL) - /* descriptors should already contain fd. */ - abort (); - node = gl_list_search (fds, (void *) (uintptr_t) fd); - if (node == NULL) - /* descriptors should already contain fd. */ - abort (); - gl_list_remove_node (fds, node); -} - -/* Open a temporary file in a temporary directory. - Registers the resulting file descriptor to be closed. */ -int -open_temp (const char *file_name, int flags, mode_t mode) -{ - int fd; - int saved_errno; - - block_fatal_signals (); - fd = open (file_name, flags, mode); /* actually open or open_safer */ - saved_errno = errno; - if (fd >= 0) - register_fd (fd); - unblock_fatal_signals (); - errno = saved_errno; - return fd; -} - -/* Open a temporary file in a temporary directory. - Registers the resulting file descriptor to be closed. */ -FILE * -fopen_temp (const char *file_name, const char *mode) -{ - FILE *fp; - int saved_errno; - - block_fatal_signals (); - fp = fopen (file_name, mode); /* actually fopen or fopen_safer */ - saved_errno = errno; - if (fp != NULL) - { - /* It is sufficient to register fileno (fp) instead of the entire fp, - because at cleanup time there is no need to do an fflush (fp); a - close (fileno (fp)) will be enough. */ - int fd = fileno (fp); - if (!(fd >= 0)) - abort (); - register_fd (fd); - } - unblock_fatal_signals (); - errno = saved_errno; - return fp; -} - -/* Close a temporary file in a temporary directory. - Unregisters the previously registered file descriptor. */ -int -close_temp (int fd) -{ - if (fd >= 0) - { - /* No blocking of signals is needed here, since a double close of a - file descriptor is harmless. */ - int result = close (fd); - int saved_errno = errno; - - /* No race condition here: we assume a single-threaded program, hence - fd cannot be re-opened here. */ - - unregister_fd (fd); - - errno = saved_errno; - return result; - } - else - return close (fd); -} - -/* Close a temporary file in a temporary directory. - Unregisters the previously registered file descriptor. */ -int -fclose_temp (FILE *fp) -{ - int fd = fileno (fp); - /* No blocking of signals is needed here, since a double close of a - file descriptor is harmless. */ - int result = fclose (fp); - int saved_errno = errno; - - /* No race condition here: we assume a single-threaded program, hence - fd cannot be re-opened here. */ - - unregister_fd (fd); - - errno = saved_errno; - return result; -} - -#if GNULIB_FWRITEERROR -/* Like fwriteerror. - Unregisters the previously registered file descriptor. */ -int -fwriteerror_temp (FILE *fp) -{ - int fd = fileno (fp); - /* No blocking of signals is needed here, since a double close of a - file descriptor is harmless. */ - int result = fwriteerror (fp); - int saved_errno = errno; - - /* No race condition here: we assume a single-threaded program, hence - fd cannot be re-opened here. */ - - unregister_fd (fd); - - errno = saved_errno; - return result; -} -#endif - -#if GNULIB_CLOSE_STREAM -/* Like close_stream. - Unregisters the previously registered file descriptor. */ -int -close_stream_temp (FILE *fp) -{ - int fd = fileno (fp); - /* No blocking of signals is needed here, since a double close of a - file descriptor is harmless. */ - int result = close_stream (fp); - int saved_errno = errno; - - /* No race condition here: we assume a single-threaded program, hence - fd cannot be re-opened here. */ - - unregister_fd (fd); - - errno = saved_errno; - return result; -} -#endif diff --git a/src/bin/m4/lib/clean-temp.h b/src/bin/m4/lib/clean-temp.h deleted file mode 100644 index 6e7c3e6c91..0000000000 --- a/src/bin/m4/lib/clean-temp.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Temporary directories and temporary files with automatic cleanup. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _CLEAN_TEMP_H -#define _CLEAN_TEMP_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Temporary directories and temporary files should be automatically removed - when the program exits either normally or through a fatal signal. We can't - rely on the "unlink before close" idiom, because it works only on Unix and - also - if no signal blocking is used - leaves a time window where a fatal - signal would not clean up the temporary file. - - Also, open file descriptors need to be closed before the temporary files - and the temporary directories can be removed, because only on Unix - (excluding Cygwin) can one remove directories containing open files. - - This module provides support for temporary directories and temporary files - inside these temporary directories. Temporary files without temporary - directories are not supported here. */ - -struct temp_dir -{ - /* The absolute pathname of the directory. */ - const char * const dir_name; - /* Whether errors during explicit cleanup are reported to standard error. */ - bool cleanup_verbose; - /* More fields are present here, but not public. */ -}; - -/* Create a temporary directory. - PREFIX is used as a prefix for the name of the temporary directory. It - should be short and still give an indication about the program. - PARENTDIR can be used to specify the parent directory; if NULL, a default - parent directory is used (either $TMPDIR or /tmp or similar). - CLEANUP_VERBOSE determines whether errors during explicit cleanup are - reported to standard error. - Return a fresh 'struct temp_dir' on success. Upon error, an error message - is shown and NULL is returned. */ -extern struct temp_dir * create_temp_dir (const char *prefix, - const char *parentdir, - bool cleanup_verbose); - -/* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that - needs to be removed before DIR can be removed. - Should be called before the file ABSOLUTE_FILE_NAME is created. */ -extern void register_temp_file (struct temp_dir *dir, - const char *absolute_file_name); - -/* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that - needs to be removed before DIR can be removed. - Should be called when the file ABSOLUTE_FILE_NAME could not be created. */ -extern void unregister_temp_file (struct temp_dir *dir, - const char *absolute_file_name); - -/* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, - that needs to be removed before DIR can be removed. - Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */ -extern void register_temp_subdir (struct temp_dir *dir, - const char *absolute_dir_name); - -/* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, - that needs to be removed before DIR can be removed. - Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be - created. */ -extern void unregister_temp_subdir (struct temp_dir *dir, - const char *absolute_dir_name); - -/* Remove the given ABSOLUTE_FILE_NAME and unregister it. - Return 0 upon success, or -1 if there was some problem. */ -extern int cleanup_temp_file (struct temp_dir *dir, - const char *absolute_file_name); - -/* Remove the given ABSOLUTE_DIR_NAME and unregister it. - Return 0 upon success, or -1 if there was some problem. */ -extern int cleanup_temp_subdir (struct temp_dir *dir, - const char *absolute_dir_name); - -/* Remove all registered files and subdirectories inside DIR. - Return 0 upon success, or -1 if there was some problem. */ -extern int cleanup_temp_dir_contents (struct temp_dir *dir); - -/* Remove all registered files and subdirectories inside DIR and DIR itself. - DIR cannot be used any more after this call. - Return 0 upon success, or -1 if there was some problem. */ -extern int cleanup_temp_dir (struct temp_dir *dir); - -/* Open a temporary file in a temporary directory. - Registers the resulting file descriptor to be closed. */ -extern int open_temp (const char *file_name, int flags, mode_t mode); -extern FILE * fopen_temp (const char *file_name, const char *mode); - -/* Close a temporary file in a temporary directory. - Unregisters the previously registered file descriptor. */ -extern int close_temp (int fd); -extern int fclose_temp (FILE *fp); - -/* Like fwriteerror. - Unregisters the previously registered file descriptor. */ -extern int fwriteerror_temp (FILE *fp); - -/* Like close_stream. - Unregisters the previously registered file descriptor. */ -extern int close_stream_temp (FILE *fp); - - -#ifdef __cplusplus -} -#endif - -#endif /* _CLEAN_TEMP_H */ diff --git a/src/bin/m4/lib/cloexec.c b/src/bin/m4/lib/cloexec.c deleted file mode 100644 index 6480006a5b..0000000000 --- a/src/bin/m4/lib/cloexec.c +++ /dev/null @@ -1,59 +0,0 @@ -/* closexec.c - set or clear the close-on-exec descriptor flag - - Copyright (C) 1991, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - The code is taken from glibc/manual/llio.texi */ - -#include - -#include "cloexec.h" - -#include -#include - -#ifndef FD_CLOEXEC -# define FD_CLOEXEC 1 -#endif - -/* Set the `FD_CLOEXEC' flag of DESC if VALUE is true, - or clear the flag if VALUE is false. - Return 0 on success, or -1 on error with `errno' set. */ - -int -set_cloexec_flag (int desc, bool value) -{ -#if defined F_GETFD && defined F_SETFD - - int flags = fcntl (desc, F_GETFD, 0); - - if (0 <= flags) - { - int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); - - if (flags == newflags - || fcntl (desc, F_SETFD, newflags) != -1) - return 0; - } - - return -1; - -#else - - return 0; - -#endif -} diff --git a/src/bin/m4/lib/cloexec.h b/src/bin/m4/lib/cloexec.h deleted file mode 100644 index c25921d6b3..0000000000 --- a/src/bin/m4/lib/cloexec.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -int set_cloexec_flag (int desc, bool value); diff --git a/src/bin/m4/lib/close-stream.c b/src/bin/m4/lib/close-stream.c deleted file mode 100644 index 72d0d6816c..0000000000 --- a/src/bin/m4/lib/close-stream.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Close a stream, with nicer error checking than fclose's. - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "close-stream.h" - -#include -#include - -#include "__fpending.h" - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -/* Close STREAM. Return 0 if successful, EOF (setting errno) - otherwise. A failure might set errno to 0 if the error number - cannot be determined. - - If a program writes *anything* to STREAM, that program should close - STREAM and make sure that it succeeds before exiting. Otherwise, - suppose that you go to the extreme of checking the return status - of every function that does an explicit write to STREAM. The last - printf can succeed in writing to the internal stream buffer, and yet - the fclose(STREAM) could still fail (due e.g., to a disk full error) - when it tries to write out that buffered data. Thus, you would be - left with an incomplete output file and the offending program would - exit successfully. Even calling fflush is not always sufficient, - since some file systems (NFS and CODA) buffer written/flushed data - until an actual close call. - - Besides, it's wasteful to check the return value from every call - that writes to STREAM -- just let the internal stream state record - the failure. That's what the ferror test is checking below. */ - -int -close_stream (FILE *stream) -{ - bool some_pending = (__fpending (stream) != 0); - bool prev_fail = (ferror (stream) != 0); - bool fclose_fail = (fclose (stream) != 0); - - /* Return an error indication if there was a previous failure or if - fclose failed, with one exception: ignore an fclose failure if - there was no previous error, no data remains to be flushed, and - fclose failed with EBADF. That can happen when a program like cp - is invoked like this `cp a b >&-' (i.e., with standard output - closed) and doesn't generate any output (hence no previous error - and nothing to be flushed). */ - - if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) - { - if (! fclose_fail) - errno = 0; - return EOF; - } - - return 0; -} diff --git a/src/bin/m4/lib/close-stream.h b/src/bin/m4/lib/close-stream.h deleted file mode 100644 index be3d4196b0..0000000000 --- a/src/bin/m4/lib/close-stream.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -int close_stream (FILE *stream); diff --git a/src/bin/m4/lib/closeout.c b/src/bin/m4/lib/closeout.c deleted file mode 100644 index 830f16f8ae..0000000000 --- a/src/bin/m4/lib/closeout.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Close standard output and standard error, exiting with a diagnostic on error. - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "closeout.h" - -#include -#include -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -#include "close-stream.h" -#include "error.h" -#include "exitfail.h" -#include "quotearg.h" - -static const char *file_name; - -/* Set the file name to be reported in the event an error is detected - by close_stdout. */ -void -close_stdout_set_file_name (const char *file) -{ - file_name = file; -} - -/* Close standard output. On error, issue a diagnostic and _exit - with status 'exit_failure'. - - Also close standard error. On error, _exit with status 'exit_failure'. - - Since close_stdout is commonly registered via 'atexit', POSIX - and the C standard both say that it should not call 'exit', - because the behavior is undefined if 'exit' is called more than - once. So it calls '_exit' instead of 'exit'. If close_stdout - is registered via atexit before other functions are registered, - the other functions can act before this _exit is invoked. - - Applications that use close_stdout should flush any streams - other than stdout and stderr before exiting, since the call to - _exit will bypass other buffer flushing. Applications should - be flushing and closing other streams anyway, to check for I/O - errors. Also, applications should not use tmpfile, since _exit - can bypass the removal of these files. - - It's important to detect such failures and exit nonzero because many - tools (most notably `make' and other build-management systems) depend - on being able to detect failure in other tools via their exit status. */ - -void -close_stdout (void) -{ - if (close_stream (stdout) != 0) - { - char const *write_error = _("write error"); - if (file_name) - error (0, errno, "%s: %s", quotearg_colon (file_name), - write_error); - else - error (0, errno, "%s", write_error); - - _exit (exit_failure); - } - - if (close_stream (stderr) != 0) - _exit (exit_failure); -} diff --git a/src/bin/m4/lib/closeout.h b/src/bin/m4/lib/closeout.h deleted file mode 100644 index 8bed23b5f1..0000000000 --- a/src/bin/m4/lib/closeout.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Close standard output and standard error. - - Copyright (C) 1998, 2000, 2003, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef CLOSEOUT_H -# define CLOSEOUT_H 1 - -# ifdef __cplusplus -extern "C" { -# endif - -void close_stdout_set_file_name (const char *file); -void close_stdout (void); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/src/bin/m4/lib/config.h b/src/bin/m4/lib/config.h deleted file mode 100644 index 33a1704f20..0000000000 --- a/src/bin/m4/lib/config.h +++ /dev/null @@ -1,606 +0,0 @@ -/* lib/config.h. Generated from config.hin by configure. */ -/* lib/config.hin. Generated from configure.ac by autoheader. */ - -/* Define this to an absolute name of . */ -#define ABSOLUTE_STDINT_H "///usr/include/stdint.h" - -/* Define this to an absolute name of . */ -#define ABSOLUTE_SYS_STAT_H "///usr/include/sys/stat.h" - -/* Define to the number of bits in type 'ptrdiff_t'. */ -#define BITSIZEOF_PTRDIFF_T 32 - -/* Define to the number of bits in type 'sig_atomic_t'. */ -#define BITSIZEOF_SIG_ATOMIC_T 32 - -/* Define to the number of bits in type 'size_t'. */ -#define BITSIZEOF_SIZE_T 32 - -/* Define to the number of bits in type 'wchar_t'. */ -#define BITSIZEOF_WCHAR_T 32 - -/* Define to the number of bits in type 'wint_t'. */ -#define BITSIZEOF_WINT_T 32 - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define to 1 if the changeword(REGEXP) functionality is wanted */ -/* #undef ENABLE_CHANGEWORD */ - -/* Define as good substitute value for EOVERFLOW. */ -/* #undef EOVERFLOW */ - -/* Define to 1 if the return value of system() disagrees with pclose(). */ -/* #undef FUNC_SYSTEM_BROKEN */ - -/* Define to 1 when using the gnulib close-stream module. */ -#define GNULIB_CLOSE_STREAM 1 - -/* Define to 1 when using the gnulib fopen-safer module. */ -#define GNULIB_FOPEN_SAFER 1 - -/* Define to 1 if you have 'alloca' after including , a header that - may be supplied by this distribution. */ -#define HAVE_ALLOCA 1 - -/* Define HAVE_ALLOCA_H for backward compatibility with older code that - includes only if HAVE_ALLOCA_H is defined. */ -#define HAVE_ALLOCA_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BP_SYM_H */ - -/* Define to 1 if you have the declaration of `clearerr_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_CLEARERR_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you - don't. */ -#define HAVE_DECL_FEOF_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `ferror_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FERROR_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `fflush_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FFLUSH_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FGETS_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `fputc_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FPUTC_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `fputs_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FPUTS_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `fread_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FREAD_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `fwrite_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_FWRITE_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `getchar_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_GETCHAR_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you - don't. */ -#define HAVE_DECL_GETC_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't. - */ -#define HAVE_DECL_GETENV 1 - -/* Define to 1 if you have the declaration of `isblank', and to 0 if you - don't. */ -/* #undef HAVE_DECL_ISBLANK */ - -/* Define to 1 if you have the declaration of `mkdir', and to 0 if you don't. - */ -#define HAVE_DECL_MKDIR 1 - -/* Define to 1 if you have the declaration of `putchar_unlocked', and to 0 if - you don't. */ -#define HAVE_DECL_PUTCHAR_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `putc_unlocked', and to 0 if you - don't. */ -#define HAVE_DECL_PUTC_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you - don't. */ -#define HAVE_DECL_STRERROR_R 1 - -/* Define to 1 if you have the declaration of `strncasecmp', and to 0 if you - don't. */ -#define HAVE_DECL_STRNCASECMP 1 - -/* Define to 1 if you have the declaration of `wcwidth', and to 0 if you - don't. */ -#define HAVE_DECL_WCWIDTH 1 - -/* Define to 1 if you have the declaration of `__fpending', and to 0 if you - don't. */ -#define HAVE_DECL___FPENDING 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_GETOPT_H 1 - -/* Define to 1 if you have the `getopt_long_only' function. */ -#define HAVE_GETOPT_LONG_ONLY 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if the compiler supports one of the keywords 'inline', - '__inline__', '__inline' and effectively inlines functions marked as such. - */ -#define HAVE_INLINE 1 - -/* Define if you have the 'intmax_t' type in or . */ -#define HAVE_INTMAX_T 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define if exists, doesn't clash with , and - declares uintmax_t. */ -#define HAVE_INTTYPES_H_WITH_UINTMAX 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_IO_H */ - -/* Define to 1 if you have the `iswcntrl' function. */ -#define HAVE_ISWCNTRL 1 - -/* Define to 1 if you have the `iswprint' function. */ -#define HAVE_ISWPRINT 1 - -/* Define if you have and nl_langinfo(CODESET). */ -#define HAVE_LANGINFO_CODESET 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if you have the 'long double' type. */ -#define HAVE_LONG_DOUBLE 1 - -/* Define if you have the 'long long' type. */ -#define HAVE_LONG_LONG 1 - -/* Define to 1 if the system has the type `long long int'. */ -#define HAVE_LONG_LONG_INT 1 - -/* Define to 1 if you have the `lstat' function. */ -#define HAVE_LSTAT 1 - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - -/* Define to 1 if you have the `mbrtowc' function. */ -#define HAVE_MBRTOWC 1 - -/* Define to 1 if you have the `mbsinit' function. */ -#define HAVE_MBSINIT 1 - -/* Define to 1 if declares mbstate_t. */ -#define HAVE_MBSTATE_T 1 - -/* Define to 1 if you have the `memchr' function. */ -#define HAVE_MEMCHR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mempcpy' function. */ -#define HAVE_MEMPCPY 1 - -/* Define to 1 if you have the `mkdtemp' function. */ -#define HAVE_MKDTEMP 1 - -/* Define to 1 if libc includes obstacks. */ -#define HAVE_OBSTACK 1 - -/* Define to 1 if you have the `pipe' function. */ -#define HAVE_PIPE 1 - -/* Define to 1 if you have the sigset_t type and the sigprocmask function. */ -#define HAVE_POSIX_SIGNALBLOCKING 1 - -/* Define to 1 if the system has the type `ptrdiff_t'. */ -#define HAVE_PTRDIFF_T 1 - -/* Define to 1 if you have the `raise' function. */ -#define HAVE_RAISE 1 - -/* Define to 1 if the system has the type `rlim_t'. */ -#define HAVE_RLIM_T 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `sigaltstack' function. */ -// #define HAVE_SIGALTSTACK 1 - -/* Define to 1 if the system has the type `sigcontext'. */ -/* #undef HAVE_SIGCONTEXT */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SIGINFO_H */ - -/* Define to 1 if the system has the type `siginfo_t'. */ -#define HAVE_SIGINFO_T 1 - -/* Define to 1 if 'sig_atomic_t' is a signed integer type. */ -#define HAVE_SIGNED_SIG_ATOMIC_T 1 - -/* Define to 1 if 'wchar_t' is a signed integer type. */ -/* #undef HAVE_SIGNED_WCHAR_T */ - -/* Define to 1 if 'wint_t' is a signed integer type. */ -/* #undef HAVE_SIGNED_WINT_T */ - -/* Define to 1 if you lack the sigprocmask function but have the sigset_t - type. */ -/* #undef HAVE_SIGSET_T */ - -/* Define to 1 if you have the `sigstack' function. */ -#define HAVE_SIGSTACK 1 - -/* Define to 1 if you have the `sigvec' function. */ -#define HAVE_SIGVEC 1 - -/* Define to 1 if the system has the type `sig_atomic_t'. */ -#define HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 - -/* Define to 1 if the system has the type `stack_t'. */ -#define HAVE_STACK_T 1 - -/* Define to 1 if stdbool.h conforms to C99. */ -#define HAVE_STDBOOL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define if exists, doesn't clash with , and declares - uintmax_t. */ -#define HAVE_STDINT_H_WITH_UINTMAX 1 - -/* Define to 1 if you have the header file. */ -// #define HAVE_STDIO_EXT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the `strerror_r' function. */ -#define HAVE_STRERROR_R 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strncasecmp' function. */ -#define HAVE_STRNCASECMP 1 - -/* Define to 1 if you have the `strtol' function. */ -#define HAVE_STRTOL 1 - -/* Define to 1 if `sa_sigaction' is member of `struct sigaction'. */ -// #define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_BITYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_INTTYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if the system has the type `unsigned long long int'. */ -#define HAVE_UNSIGNED_LONG_LONG_INT 1 - -/* Define to 1 if you have the `vasnprintf' function. */ -/* #undef HAVE_VASNPRINTF */ - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WCHAR_H 1 - -/* Define if you have the 'wchar_t' type. */ -#define HAVE_WCHAR_T 1 - -/* Define to 1 if you have the `wcrtomb' function. */ -#define HAVE_WCRTOMB 1 - -/* Define to 1 if you have the `wcscoll' function. */ -#define HAVE_WCSCOLL 1 - -/* Define to 1 if you have the `wcslen' function. */ -#define HAVE_WCSLEN 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WCTYPE_H 1 - -/* Define to 1 if you have the `wcwidth' function. */ -#define HAVE_WCWIDTH 1 - -/* Define if you have the 'wint_t' type. */ -#define HAVE_WINT_T 1 - -/* Define to 1 if the system has the type `_Bool'. */ -#define HAVE__BOOL 1 - -/* Define to 1 if you have the `__fpending' function. */ -#define HAVE___FPENDING 1 - -/* Define to 1 if you have the `__secure_getenv' function. */ -// #define HAVE___SECURE_GETENV 1 - -/* If malloc(0) is != NULL, define this to 1. Otherwise define this to 0. */ -#define MALLOC_0_IS_NONNULL 1 - -/* Name of package */ -#define PACKAGE "m4" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "bug-m4@gnu.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "GNU M4" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU M4 1.4.8" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "m4" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.4.8" - -/* the number of pending output bytes on stream `fp' */ -/* #undef PENDING_OUTPUT_N_BYTES */ -#define PENDING_OUTPUT_N_BYTES fp->_IO_write_ptr - fp->_IO_write_base - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'ptrdiff_t'. */ -#define PTRDIFF_T_SUFFIX - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define if lists must be signal-safe. */ -#define SIGNAL_SAFE_LIST 1 - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'sig_atomic_t'. */ -#define SIG_ATOMIC_T_SUFFIX - -/* Define as the maximum value of type 'size_t', if the system doesn't define - it. */ -/* #undef SIZE_MAX */ - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'size_t'. */ -#define SIZE_T_SUFFIX u - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if the `S_IS*' macros in do not work properly. */ -/* #undef STAT_MACROS_BROKEN */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if strerror_r returns char *. */ -/* #undef STRERROR_R_CHAR_P */ - -/* Define to 1 if using stack overflow detection */ -// #define USE_STACKOVF 1 - -/* Define to 1 if you want getc etc. to use unlocked I/O if available. - Unlocked I/O can improve performance in unithreaded apps, but it is not - safe for multithreaded apps. */ -#define USE_UNLOCKED_IO 1 - -/* Version number of package */ -#define VERSION "1.4.8" - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'wchar_t'. */ -#define WCHAR_T_SUFFIX u - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'wint_t'. */ -#define WINT_T_SUFFIX u - -/* Define to 1 if malloc debugging is enabled */ -/* #undef WITH_DMALLOC */ - -/* Define to 1 if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -/* # undef _ALL_SOURCE */ -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#define _FILE_OFFSET_BITS 64 - -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define if you want regoff_t to be at least as wide POSIX requires. */ -/* #undef _REGEX_LARGE_OFFSETS */ - -/* Enable extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# define __EXTENSIONS__ 1 -#endif -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS 1 -#endif -#ifndef _TANDEM_SOURCE -# define _TANDEM_SOURCE 1 -#endif - -/* Define to rpl_ if the getopt replacement functions and variables should be - used. */ -/* #undef __GETOPT_PREFIX */ - -/* Define to rpl_ if the mkstemp replacement function should be used. */ -/* #undef __MKSTEMP_PREFIX */ - -/* Define to rpl_free if the replacement function should be used. */ -/* #undef free */ - -/* A replacement for va_copy, if needed. */ -#define gl_va_copy(a,b) ((a) = (b)) - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to long or long long if and don't define. */ -/* #undef intmax_t */ - -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - -/* Define to a type if does not define. */ -/* #undef mbstate_t */ - -/* Define to rpl_re_comp if the replacement should be used. */ -/* #undef re_comp */ - -/* Define to rpl_re_compile_fastmap if the replacement should be used. */ -/* #undef re_compile_fastmap */ - -/* Define to rpl_re_compile_pattern if the replacement should be used. */ -/* #undef re_compile_pattern */ - -/* Define to rpl_re_exec if the replacement should be used. */ -/* #undef re_exec */ - -/* Define to rpl_re_match if the replacement should be used. */ -/* #undef re_match */ - -/* Define to rpl_re_match_2 if the replacement should be used. */ -/* #undef re_match_2 */ - -/* Define to rpl_re_search if the replacement should be used. */ -/* #undef re_search */ - -/* Define to rpl_re_search_2 if the replacement should be used. */ -/* #undef re_search_2 */ - -/* Define to rpl_re_set_registers if the replacement should be used. */ -/* #undef re_set_registers */ - -/* Define to rpl_re_set_syntax if the replacement should be used. */ -/* #undef re_set_syntax */ - -/* Define to rpl_re_syntax_options if the replacement should be used. */ -/* #undef re_syntax_options */ - -/* Define to rpl_regcomp if the replacement should be used. */ -/* #undef regcomp */ - -/* Define to rpl_regerror if the replacement should be used. */ -/* #undef regerror */ - -/* Define to rpl_regexec if the replacement should be used. */ -/* #undef regexec */ - -/* Define to rpl_regfree if the replacement should be used. */ -/* #undef regfree */ - -/* Define to equivalent of C99 restrict keyword, or to nothing if this is not - supported. Do not define if restrict is supported directly. */ -#define restrict __restrict - -/* Define to int if rlim_t is not defined in sys/resource.h */ -/* #undef rlim_t */ - -/* Define as an integer type suitable for memory locations that can be - accessed atomically even in the presence of asynchnonous signals. */ -/* #undef sig_atomic_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define as a signed type of the same size as size_t. */ -/* #undef ssize_t */ - -/* Define to struct sigaltstack if stack_t is not in signal.h */ -/* #undef stack_t */ - -/* Define as a macro for copying va_list variables. */ -#if __GNUC__ < 3 -#define va_copy gl_va_copy -#endif diff --git a/src/bin/m4/lib/config.hin b/src/bin/m4/lib/config.hin deleted file mode 100644 index fef9579162..0000000000 --- a/src/bin/m4/lib/config.hin +++ /dev/null @@ -1,602 +0,0 @@ -/* lib/config.hin. Generated from configure.ac by autoheader. */ - -/* Define this to an absolute name of . */ -#undef ABSOLUTE_STDINT_H - -/* Define this to an absolute name of . */ -#undef ABSOLUTE_SYS_STAT_H - -/* Define to the number of bits in type 'ptrdiff_t'. */ -#undef BITSIZEOF_PTRDIFF_T - -/* Define to the number of bits in type 'sig_atomic_t'. */ -#undef BITSIZEOF_SIG_ATOMIC_T - -/* Define to the number of bits in type 'size_t'. */ -#undef BITSIZEOF_SIZE_T - -/* Define to the number of bits in type 'wchar_t'. */ -#undef BITSIZEOF_WCHAR_T - -/* Define to the number of bits in type 'wint_t'. */ -#undef BITSIZEOF_WINT_T - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -#undef CRAY_STACKSEG_END - -/* Define to 1 if using `alloca.c'. */ -#undef C_ALLOCA - -/* Define to 1 if the changeword(REGEXP) functionality is wanted */ -#undef ENABLE_CHANGEWORD - -/* Define as good substitute value for EOVERFLOW. */ -#undef EOVERFLOW - -/* Define to 1 if the return value of system() disagrees with pclose(). */ -#undef FUNC_SYSTEM_BROKEN - -/* Define to 1 when using the gnulib close-stream module. */ -#undef GNULIB_CLOSE_STREAM - -/* Define to 1 when using the gnulib fopen-safer module. */ -#undef GNULIB_FOPEN_SAFER - -/* Define to 1 if you have 'alloca' after including , a header that - may be supplied by this distribution. */ -#undef HAVE_ALLOCA - -/* Define HAVE_ALLOCA_H for backward compatibility with older code that - includes only if HAVE_ALLOCA_H is defined. */ -#undef HAVE_ALLOCA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_BP_SYM_H - -/* Define to 1 if you have the declaration of `clearerr_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_CLEARERR_UNLOCKED - -/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you - don't. */ -#undef HAVE_DECL_FEOF_UNLOCKED - -/* Define to 1 if you have the declaration of `ferror_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FERROR_UNLOCKED - -/* Define to 1 if you have the declaration of `fflush_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FFLUSH_UNLOCKED - -/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FGETS_UNLOCKED - -/* Define to 1 if you have the declaration of `fputc_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FPUTC_UNLOCKED - -/* Define to 1 if you have the declaration of `fputs_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FPUTS_UNLOCKED - -/* Define to 1 if you have the declaration of `fread_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FREAD_UNLOCKED - -/* Define to 1 if you have the declaration of `fwrite_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_FWRITE_UNLOCKED - -/* Define to 1 if you have the declaration of `getchar_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_GETCHAR_UNLOCKED - -/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you - don't. */ -#undef HAVE_DECL_GETC_UNLOCKED - -/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't. - */ -#undef HAVE_DECL_GETENV - -/* Define to 1 if you have the declaration of `isblank', and to 0 if you - don't. */ -#undef HAVE_DECL_ISBLANK - -/* Define to 1 if you have the declaration of `mkdir', and to 0 if you don't. - */ -#undef HAVE_DECL_MKDIR - -/* Define to 1 if you have the declaration of `putchar_unlocked', and to 0 if - you don't. */ -#undef HAVE_DECL_PUTCHAR_UNLOCKED - -/* Define to 1 if you have the declaration of `putc_unlocked', and to 0 if you - don't. */ -#undef HAVE_DECL_PUTC_UNLOCKED - -/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you - don't. */ -#undef HAVE_DECL_STRERROR_R - -/* Define to 1 if you have the declaration of `strncasecmp', and to 0 if you - don't. */ -#undef HAVE_DECL_STRNCASECMP - -/* Define to 1 if you have the declaration of `wcwidth', and to 0 if you - don't. */ -#undef HAVE_DECL_WCWIDTH - -/* Define to 1 if you have the declaration of `__fpending', and to 0 if you - don't. */ -#undef HAVE_DECL___FPENDING - -/* Define to 1 if you have the header file. */ -#undef HAVE_GETOPT_H - -/* Define to 1 if you have the `getopt_long_only' function. */ -#undef HAVE_GETOPT_LONG_ONLY - -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - -/* Define to 1 if the compiler supports one of the keywords 'inline', - '__inline__', '__inline' and effectively inlines functions marked as such. - */ -#undef HAVE_INLINE - -/* Define if you have the 'intmax_t' type in or . */ -#undef HAVE_INTMAX_T - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define if exists, doesn't clash with , and - declares uintmax_t. */ -#undef HAVE_INTTYPES_H_WITH_UINTMAX - -/* Define to 1 if you have the header file. */ -#undef HAVE_IO_H - -/* Define to 1 if you have the `iswcntrl' function. */ -#undef HAVE_ISWCNTRL - -/* Define to 1 if you have the `iswprint' function. */ -#undef HAVE_ISWPRINT - -/* Define if you have and nl_langinfo(CODESET). */ -#undef HAVE_LANGINFO_CODESET - -/* Define to 1 if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LOCALE_H - -/* Define if you have the 'long double' type. */ -#undef HAVE_LONG_DOUBLE - -/* Define if you have the 'long long' type. */ -#undef HAVE_LONG_LONG - -/* Define to 1 if the system has the type `long long int'. */ -#undef HAVE_LONG_LONG_INT - -/* Define to 1 if you have the `lstat' function. */ -#undef HAVE_LSTAT - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the `mbrtowc' function. */ -#undef HAVE_MBRTOWC - -/* Define to 1 if you have the `mbsinit' function. */ -#undef HAVE_MBSINIT - -/* Define to 1 if declares mbstate_t. */ -#undef HAVE_MBSTATE_T - -/* Define to 1 if you have the `memchr' function. */ -#undef HAVE_MEMCHR - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `mempcpy' function. */ -#undef HAVE_MEMPCPY - -/* Define to 1 if you have the `mkdtemp' function. */ -#undef HAVE_MKDTEMP - -/* Define to 1 if libc includes obstacks. */ -#undef HAVE_OBSTACK - -/* Define to 1 if you have the `pipe' function. */ -#undef HAVE_PIPE - -/* Define to 1 if you have the sigset_t type and the sigprocmask function. */ -#undef HAVE_POSIX_SIGNALBLOCKING - -/* Define to 1 if the system has the type `ptrdiff_t'. */ -#undef HAVE_PTRDIFF_T - -/* Define to 1 if you have the `raise' function. */ -#undef HAVE_RAISE - -/* Define to 1 if the system has the type `rlim_t'. */ -#undef HAVE_RLIM_T - -/* Define to 1 if you have the `sigaction' function. */ -#undef HAVE_SIGACTION - -/* Define to 1 if you have the `sigaltstack' function. */ -#undef HAVE_SIGALTSTACK - -/* Define to 1 if the system has the type `sigcontext'. */ -#undef HAVE_SIGCONTEXT - -/* Define to 1 if you have the header file. */ -#undef HAVE_SIGINFO_H - -/* Define to 1 if the system has the type `siginfo_t'. */ -#undef HAVE_SIGINFO_T - -/* Define to 1 if 'sig_atomic_t' is a signed integer type. */ -#undef HAVE_SIGNED_SIG_ATOMIC_T - -/* Define to 1 if 'wchar_t' is a signed integer type. */ -#undef HAVE_SIGNED_WCHAR_T - -/* Define to 1 if 'wint_t' is a signed integer type. */ -#undef HAVE_SIGNED_WINT_T - -/* Define to 1 if you lack the sigprocmask function but have the sigset_t - type. */ -#undef HAVE_SIGSET_T - -/* Define to 1 if you have the `sigstack' function. */ -#undef HAVE_SIGSTACK - -/* Define to 1 if you have the `sigvec' function. */ -#undef HAVE_SIGVEC - -/* Define to 1 if the system has the type `sig_atomic_t'. */ -#undef HAVE_SIG_ATOMIC_T - -/* Define to 1 if you have the `snprintf' function. */ -#undef HAVE_SNPRINTF - -/* Define to 1 if the system has the type `stack_t'. */ -#undef HAVE_STACK_T - -/* Define to 1 if stdbool.h conforms to C99. */ -#undef HAVE_STDBOOL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define if exists, doesn't clash with , and declares - uintmax_t. */ -#undef HAVE_STDINT_H_WITH_UINTMAX - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDIO_EXT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - -/* Define to 1 if you have the `strerror_r' function. */ -#undef HAVE_STRERROR_R - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strncasecmp' function. */ -#undef HAVE_STRNCASECMP - -/* Define to 1 if you have the `strtol' function. */ -#undef HAVE_STRTOL - -/* Define to 1 if `sa_sigaction' is member of `struct sigaction'. */ -#undef HAVE_STRUCT_SIGACTION_SA_SIGACTION - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_BITYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_INTTYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if the system has the type `unsigned long long int'. */ -#undef HAVE_UNSIGNED_LONG_LONG_INT - -/* Define to 1 if you have the `vasnprintf' function. */ -#undef HAVE_VASNPRINTF - -/* Define to 1 if you have the `vasprintf' function. */ -#undef HAVE_VASPRINTF - -/* Define to 1 if you have the header file. */ -#undef HAVE_WCHAR_H - -/* Define if you have the 'wchar_t' type. */ -#undef HAVE_WCHAR_T - -/* Define to 1 if you have the `wcrtomb' function. */ -#undef HAVE_WCRTOMB - -/* Define to 1 if you have the `wcscoll' function. */ -#undef HAVE_WCSCOLL - -/* Define to 1 if you have the `wcslen' function. */ -#undef HAVE_WCSLEN - -/* Define to 1 if you have the header file. */ -#undef HAVE_WCTYPE_H - -/* Define to 1 if you have the `wcwidth' function. */ -#undef HAVE_WCWIDTH - -/* Define if you have the 'wint_t' type. */ -#undef HAVE_WINT_T - -/* Define to 1 if the system has the type `_Bool'. */ -#undef HAVE__BOOL - -/* Define to 1 if you have the `__fpending' function. */ -#undef HAVE___FPENDING - -/* Define to 1 if you have the `__secure_getenv' function. */ -#undef HAVE___SECURE_GETENV - -/* If malloc(0) is != NULL, define this to 1. Otherwise define this to 0. */ -#undef MALLOC_0_IS_NONNULL - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* the number of pending output bytes on stream `fp' */ -#undef PENDING_OUTPUT_N_BYTES - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'ptrdiff_t'. */ -#undef PTRDIFF_T_SUFFIX - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - -/* Define if lists must be signal-safe. */ -#undef SIGNAL_SAFE_LIST - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'sig_atomic_t'. */ -#undef SIG_ATOMIC_T_SUFFIX - -/* Define as the maximum value of type 'size_t', if the system doesn't define - it. */ -#undef SIZE_MAX - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'size_t'. */ -#undef SIZE_T_SUFFIX - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -#undef STACK_DIRECTION - -/* Define to 1 if the `S_IS*' macros in do not work properly. */ -#undef STAT_MACROS_BROKEN - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 if strerror_r returns char *. */ -#undef STRERROR_R_CHAR_P - -/* Define to 1 if using stack overflow detection */ -#undef USE_STACKOVF - -/* Define to 1 if you want getc etc. to use unlocked I/O if available. - Unlocked I/O can improve performance in unithreaded apps, but it is not - safe for multithreaded apps. */ -#undef USE_UNLOCKED_IO - -/* Version number of package */ -#undef VERSION - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'wchar_t'. */ -#undef WCHAR_T_SUFFIX - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'wint_t'. */ -#undef WINT_T_SUFFIX - -/* Define to 1 if malloc debugging is enabled */ -#undef WITH_DMALLOC - -/* Define to 1 if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#undef _FILE_OFFSET_BITS - -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# undef _GNU_SOURCE -#endif - -/* Define for large files, on AIX-style hosts. */ -#undef _LARGE_FILES - -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE - -/* Define if you want regoff_t to be at least as wide POSIX requires. */ -#undef _REGEX_LARGE_OFFSETS - -/* Enable extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif - -/* Define to rpl_ if the getopt replacement functions and variables should be - used. */ -#undef __GETOPT_PREFIX - -/* Define to rpl_ if the mkstemp replacement function should be used. */ -#undef __MKSTEMP_PREFIX - -/* Define to rpl_free if the replacement function should be used. */ -#undef free - -/* A replacement for va_copy, if needed. */ -#define gl_va_copy(a,b) ((a) = (b)) - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to long or long long if and don't define. */ -#undef intmax_t - -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc - -/* Define to a type if does not define. */ -#undef mbstate_t - -/* Define to rpl_re_comp if the replacement should be used. */ -#undef re_comp - -/* Define to rpl_re_compile_fastmap if the replacement should be used. */ -#undef re_compile_fastmap - -/* Define to rpl_re_compile_pattern if the replacement should be used. */ -#undef re_compile_pattern - -/* Define to rpl_re_exec if the replacement should be used. */ -#undef re_exec - -/* Define to rpl_re_match if the replacement should be used. */ -#undef re_match - -/* Define to rpl_re_match_2 if the replacement should be used. */ -#undef re_match_2 - -/* Define to rpl_re_search if the replacement should be used. */ -#undef re_search - -/* Define to rpl_re_search_2 if the replacement should be used. */ -#undef re_search_2 - -/* Define to rpl_re_set_registers if the replacement should be used. */ -#undef re_set_registers - -/* Define to rpl_re_set_syntax if the replacement should be used. */ -#undef re_set_syntax - -/* Define to rpl_re_syntax_options if the replacement should be used. */ -#undef re_syntax_options - -/* Define to rpl_regcomp if the replacement should be used. */ -#undef regcomp - -/* Define to rpl_regerror if the replacement should be used. */ -#undef regerror - -/* Define to rpl_regexec if the replacement should be used. */ -#undef regexec - -/* Define to rpl_regfree if the replacement should be used. */ -#undef regfree - -/* Define to equivalent of C99 restrict keyword, or to nothing if this is not - supported. Do not define if restrict is supported directly. */ -#undef restrict - -/* Define to int if rlim_t is not defined in sys/resource.h */ -#undef rlim_t - -/* Define as an integer type suitable for memory locations that can be - accessed atomically even in the presence of asynchnonous signals. */ -#undef sig_atomic_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define as a signed type of the same size as size_t. */ -#undef ssize_t - -/* Define to struct sigaltstack if stack_t is not in signal.h */ -#undef stack_t - -/* Define as a macro for copying va_list variables. */ -#undef va_copy diff --git a/src/bin/m4/lib/dup-safer.c b/src/bin/m4/lib/dup-safer.c deleted file mode 100644 index d0606eeb4c..0000000000 --- a/src/bin/m4/lib/dup-safer.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Invoke dup, but avoid some glitches. - - Copyright (C) 2001, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include - -#include "unistd-safer.h" - -#include - -#include -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif - -/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or - STDERR_FILENO. */ - -int -dup_safer (int fd) -{ -#ifdef F_DUPFD - return fcntl (fd, F_DUPFD, STDERR_FILENO + 1); -#else - /* fd_safer calls us back, but eventually the recursion unwinds and - does the right thing. */ - return fd_safer (dup (fd)); -#endif -} diff --git a/src/bin/m4/lib/error.c b/src/bin/m4/lib/error.c deleted file mode 100644 index cf86343320..0000000000 --- a/src/bin/m4/lib/error.c +++ /dev/null @@ -1,338 +0,0 @@ -/* Error handler for noninteractive utilities - Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by David MacKenzie . */ - -#if !_LIBC -# include -#endif - -#include "error.h" - -#include -#include -#include -#include - -#if !_LIBC && ENABLE_NLS -# include "gettext.h" -#endif - -#ifdef _LIBC -# include -# include -# include -# include -# define mbsrtowcs __mbsrtowcs -#endif - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#ifndef _ -# define _(String) String -#endif - -/* If NULL, error will flush stdout, then print on stderr the program - name, a colon and a space. Otherwise, error will call this - function without parameters instead. */ -void (*error_print_progname) (void); - -/* This variable is incremented each time `error' is called. */ -unsigned int error_message_count; - -#ifdef _LIBC -/* In the GNU C library, there is a predefined variable for this. */ - -# define program_name program_invocation_name -# include -# include -# include - -/* In GNU libc we want do not want to use the common name `error' directly. - Instead make it a weak alias. */ -extern void __error (int status, int errnum, const char *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern void __error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, - ...) - __attribute__ ((__format__ (__printf__, 5, 6)));; -# define error __error -# define error_at_line __error_at_line - -# include -# define fflush(s) INTUSE(_IO_fflush) (s) -# undef putc -# define putc(c, fp) INTUSE(_IO_putc) (c, fp) - -# include - -#else /* not _LIBC */ - -# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P -# ifndef HAVE_DECL_STRERROR_R -"this configure-time declaration test was not run" -# endif -char *strerror_r (); -# endif - -/* The calling program should define program_name and set it to the - name of the executing program. */ -extern char *program_name; - -# if HAVE_STRERROR_R || defined strerror_r -# define __strerror_r strerror_r -# endif /* HAVE_STRERROR_R || defined strerror_r */ -#endif /* not _LIBC */ - -static void -print_errno_message (int errnum) -{ - char const *s; - -#if defined HAVE_STRERROR_R || _LIBC - char errbuf[1024]; -# if STRERROR_R_CHAR_P || _LIBC - s = __strerror_r (errnum, errbuf, sizeof errbuf); -# else - if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) - s = errbuf; - else - s = 0; -# endif -#else - s = strerror (errnum); -#endif - -#if !_LIBC - if (! s) - s = _("Unknown system error"); -#endif - -#if _LIBC - __fxprintf (NULL, ": %s", s); -#else - fprintf (stderr, ": %s", s); -#endif -} - -static void -error_tail (int status, int errnum, const char *message, va_list args) -{ -#if _LIBC - if (_IO_fwide (stderr, 0) > 0) - { -# define ALLOCA_LIMIT 2000 - size_t len = strlen (message) + 1; - wchar_t *wmessage = NULL; - mbstate_t st; - size_t res; - const char *tmp; - bool use_malloc = false; - - while (1) - { - if (__libc_use_alloca (len * sizeof (wchar_t))) - wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); - else - { - if (!use_malloc) - wmessage = NULL; - - wchar_t *p = (wchar_t *) realloc (wmessage, - len * sizeof (wchar_t)); - if (p == NULL) - { - free (wmessage); - fputws_unlocked (L"out of memory\n", stderr); - return; - } - wmessage = p; - use_malloc = true; - } - - memset (&st, '\0', sizeof (st)); - tmp = message; - - res = mbsrtowcs (wmessage, &tmp, len, &st); - if (res != len) - break; - - if (__builtin_expect (len >= SIZE_MAX / 2, 0)) - { - /* This really should not happen if everything is fine. */ - res = (size_t) -1; - break; - } - - len *= 2; - } - - if (res == (size_t) -1) - { - /* The string cannot be converted. */ - if (use_malloc) - { - free (wmessage); - use_malloc = false; - } - wmessage = (wchar_t *) L"???"; - } - - __vfwprintf (stderr, wmessage, args); - - if (use_malloc) - free (wmessage); - } - else -#endif - vfprintf (stderr, message, args); - va_end (args); - - ++error_message_count; - if (errnum) - print_errno_message (errnum); -#if _LIBC - __fxprintf (NULL, "\n"); -#else - putc ('\n', stderr); -#endif - fflush (stderr); - if (status) - exit (status); -} - - -/* Print the program name and error message MESSAGE, which is a printf-style - format string with optional args. - If ERRNUM is nonzero, print its corresponding system error message. - Exit with status STATUS if it is nonzero. */ -void -error (int status, int errnum, const char *message, ...) -{ - va_list args; - -#if defined _LIBC && defined __libc_ptf_call - /* We do not want this call to be cut short by a thread - cancellation. Therefore disable cancellation for now. */ - int state = PTHREAD_CANCEL_ENABLE; - __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); -#endif - - fflush (stdout); -#ifdef _LIBC - _IO_flockfile (stderr); -#endif - if (error_print_progname) - (*error_print_progname) (); - else - { -#if _LIBC - __fxprintf (NULL, "%s: ", program_name); -#else - fprintf (stderr, "%s: ", program_name); -#endif - } - - va_start (args, message); - error_tail (status, errnum, message, args); - -#ifdef _LIBC - _IO_funlockfile (stderr); -# ifdef __libc_ptf_call - __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); -# endif -#endif -} - -/* Sometimes we want to have at most one error per line. This - variable controls whether this mode is selected or not. */ -int error_one_per_line; - -void -error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, ...) -{ - va_list args; - - if (error_one_per_line) - { - static const char *old_file_name; - static unsigned int old_line_number; - - if (old_line_number == line_number - && (file_name == old_file_name - || strcmp (old_file_name, file_name) == 0)) - /* Simply return and print nothing. */ - return; - - old_file_name = file_name; - old_line_number = line_number; - } - -#if defined _LIBC && defined __libc_ptf_call - /* We do not want this call to be cut short by a thread - cancellation. Therefore disable cancellation for now. */ - int state = PTHREAD_CANCEL_ENABLE; - __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); -#endif - - fflush (stdout); -#ifdef _LIBC - _IO_flockfile (stderr); -#endif - if (error_print_progname) - (*error_print_progname) (); - else - { -#if _LIBC - __fxprintf (NULL, "%s:", program_name); -#else - fprintf (stderr, "%s:", program_name); -#endif - } - -#if _LIBC - __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); -#else - fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); -#endif - - va_start (args, message); - error_tail (status, errnum, message, args); - -#ifdef _LIBC - _IO_funlockfile (stderr); -# ifdef __libc_ptf_call - __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); -# endif -#endif -} - -#ifdef _LIBC -/* Make the weak alias. */ -# undef error -# undef error_at_line -weak_alias (__error, error) -weak_alias (__error_at_line, error_at_line) -#endif diff --git a/src/bin/m4/lib/error.h b/src/bin/m4/lib/error.h deleted file mode 100644 index 5a5f247658..0000000000 --- a/src/bin/m4/lib/error.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Declaration for error-reporting function - Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _ERROR_H -#define _ERROR_H 1 - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ -# define __attribute__(Spec) /* empty */ -# endif -/* The __-protected variants of `format' and `printf' attributes - are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __format__ format -# define __printf__ printf -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Print a message with `fprintf (stderr, FORMAT, ...)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ - -extern void error (int __status, int __errnum, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); - -extern void error_at_line (int __status, int __errnum, const char *__fname, - unsigned int __lineno, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 5, 6))); - -/* If NULL, error will flush stdout, then print on stderr the program - name, a colon and a space. Otherwise, error will call this - function without parameters instead. */ -extern void (*error_print_progname) (void); - -/* This variable is incremented each time `error' is called. */ -extern unsigned int error_message_count; - -/* Sometimes we want to have at most one error per line. This - variable controls whether this mode is selected or not. */ -extern int error_one_per_line; - -#ifdef __cplusplus -} -#endif - -#endif /* error.h */ diff --git a/src/bin/m4/lib/exit.h b/src/bin/m4/lib/exit.h deleted file mode 100644 index e8f7738838..0000000000 --- a/src/bin/m4/lib/exit.h +++ /dev/null @@ -1,32 +0,0 @@ -/* exit() function. - Copyright (C) 1995, 2001 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _EXIT_H -#define _EXIT_H - -/* Get exit() declaration. */ -#include - -/* Some systems do not define EXIT_*, despite otherwise supporting C89. */ -#ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -#endif -#ifndef EXIT_FAILURE -# define EXIT_FAILURE 1 -#endif - -#endif /* _EXIT_H */ diff --git a/src/bin/m4/lib/exitfail.c b/src/bin/m4/lib/exitfail.c deleted file mode 100644 index 97abc674ec..0000000000 --- a/src/bin/m4/lib/exitfail.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Failure exit status - - Copyright (C) 2002, 2003, 2005, 2006 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 2, 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; see the file COPYING. - If not, write to the Free Software Foundation, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "exitfail.h" -#include "exit.h" - -int volatile exit_failure = EXIT_FAILURE; diff --git a/src/bin/m4/lib/exitfail.h b/src/bin/m4/lib/exitfail.h deleted file mode 100644 index e46cf9c166..0000000000 --- a/src/bin/m4/lib/exitfail.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Failure exit status - - Copyright (C) 2002 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 2, 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; see the file COPYING. - If not, write to the Free Software Foundation, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -extern int volatile exit_failure; diff --git a/src/bin/m4/lib/fatal-signal.c b/src/bin/m4/lib/fatal-signal.c deleted file mode 100644 index e9c9d04850..0000000000 --- a/src/bin/m4/lib/fatal-signal.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Emergency actions in case of a fatal signal. - Copyright (C) 2003-2004, 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2003. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - - -#include - -/* Specification. */ -#include "fatal-signal.h" - -#include -#include -#include -#include - -#include "sigprocmask.h" -#include "xalloc.h" - -#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) - - -/* ========================================================================= */ - - -/* The list of fatal signals. - These are those signals whose default action is to terminate the process - without a core dump, except - SIGKILL - because it cannot be caught, - SIGALRM SIGUSR1 SIGUSR2 SIGPOLL SIGIO SIGLOST - because applications - often use them for their own purpose, - SIGPROF SIGVTALRM - because they are used for profiling, - SIGSTKFLT - because it is more similar to SIGFPE, SIGSEGV, SIGBUS, - SIGSYS - because it is more similar to SIGABRT, SIGSEGV, - SIGPWR - because it of too special use, - SIGRTMIN...SIGRTMAX - because they are reserved for application use. - plus - SIGXCPU, SIGXFSZ - because they are quite similar to SIGTERM. */ - -static int fatal_signals[] = - { - /* ISO C 99 signals. */ -#ifdef SIGINT - SIGINT, -#endif -#ifdef SIGTERM - SIGTERM, -#endif - /* POSIX:2001 signals. */ -#ifdef SIGHUP - SIGHUP, -#endif -#ifdef SIGPIPE - SIGPIPE, -#endif - /* BSD signals. */ -#ifdef SIGXCPU - SIGXCPU, -#endif -#ifdef SIGXFSZ - SIGXFSZ, -#endif - /* Woe32 signals. */ -#ifdef SIGBREAK - SIGBREAK, -#endif - 0 - }; - -#define num_fatal_signals (SIZEOF (fatal_signals) - 1) - -/* Eliminate signals whose signal handler is SIG_IGN. */ - -static void -init_fatal_signals (void) -{ - static bool fatal_signals_initialized = false; - if (!fatal_signals_initialized) - { -#if HAVE_SIGACTION - size_t i; - - for (i = 0; i < num_fatal_signals; i++) - { - struct sigaction action; - - if (sigaction (fatal_signals[i], NULL, &action) >= 0 - && action.sa_handler == SIG_IGN) - fatal_signals[i] = -1; - } -#endif - - fatal_signals_initialized = true; - } -} - - -/* ========================================================================= */ - - -typedef void (*action_t) (void); - -/* Type of an entry in the actions array. - The 'action' field is accessed from within the fatal_signal_handler(), - therefore we mark it as 'volatile'. */ -typedef struct -{ - volatile action_t action; -} -actions_entry_t; - -/* The registered cleanup actions. */ -static actions_entry_t static_actions[32]; -static actions_entry_t * volatile actions = static_actions; -static sig_atomic_t volatile actions_count = 0; -static size_t actions_allocated = SIZEOF (static_actions); - - -/* Uninstall the handlers. */ -static inline void -uninstall_handlers () -{ - size_t i; - - for (i = 0; i < num_fatal_signals; i++) - if (fatal_signals[i] >= 0) - signal (fatal_signals[i], SIG_DFL); -} - - -/* The signal handler. It gets called asynchronously. */ -static void -fatal_signal_handler (int sig) -{ - for (;;) - { - /* Get the last registered cleanup action, in a reentrant way. */ - action_t action; - size_t n = actions_count; - if (n == 0) - break; - n--; - actions_count = n; - action = actions[n].action; - /* Execute the action. */ - action (); - } - - /* Now execute the signal's default action. - If signal() blocks the signal being delivered for the duration of the - signal handler's execution, the re-raised signal is delivered when this - handler returns; otherwise it is delivered already during raise(). */ - uninstall_handlers (); -#if HAVE_RAISE - raise (sig); -#else - kill (getpid (), sig); -#endif -} - - -/* Install the handlers. */ -static inline void -install_handlers () -{ - size_t i; - - for (i = 0; i < num_fatal_signals; i++) - if (fatal_signals[i] >= 0) - signal (fatal_signals[i], &fatal_signal_handler); -} - - -/* Register a cleanup function to be executed when a catchable fatal signal - occurs. */ -void -at_fatal_signal (action_t action) -{ - static bool cleanup_initialized = false; - if (!cleanup_initialized) - { - init_fatal_signals (); - install_handlers (); - cleanup_initialized = true; - } - - if (actions_count == actions_allocated) - { - /* Extend the actions array. Note that we cannot use xrealloc(), - because then the cleanup() function could access an already - deallocated array. */ - actions_entry_t *old_actions = actions; - size_t old_actions_allocated = actions_allocated; - size_t new_actions_allocated = 2 * actions_allocated; - actions_entry_t *new_actions = - XNMALLOC (new_actions_allocated, actions_entry_t); - size_t k; - - /* Don't use memcpy() here, because memcpy takes non-volatile arguments - and is therefore not guaranteed to complete all memory stores before - the next statement. */ - for (k = 0; k < old_actions_allocated; k++) - new_actions[k] = old_actions[k]; - actions = new_actions; - actions_allocated = new_actions_allocated; - /* Now we can free the old actions array. */ - if (old_actions != static_actions) - free (old_actions); - } - /* The two uses of 'volatile' in the types above (and ISO C 99 section - 5.1.2.3.(5)) ensure that we increment the actions_count only after - the new action has been written to the memory location - actions[actions_count]. */ - actions[actions_count].action = action; - actions_count++; -} - - -/* ========================================================================= */ - - -static sigset_t fatal_signal_set; - -static void -init_fatal_signal_set () -{ - static bool fatal_signal_set_initialized = false; - if (!fatal_signal_set_initialized) - { - size_t i; - - init_fatal_signals (); - - sigemptyset (&fatal_signal_set); - for (i = 0; i < num_fatal_signals; i++) - if (fatal_signals[i] >= 0) - sigaddset (&fatal_signal_set, fatal_signals[i]); - - fatal_signal_set_initialized = true; - } -} - -/* Temporarily delay the catchable fatal signals. */ -void -block_fatal_signals () -{ - init_fatal_signal_set (); - sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL); -} - -/* Stop delaying the catchable fatal signals. */ -void -unblock_fatal_signals () -{ - init_fatal_signal_set (); - sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL); -} diff --git a/src/bin/m4/lib/fatal-signal.h b/src/bin/m4/lib/fatal-signal.h deleted file mode 100644 index 3e6f677a87..0000000000 --- a/src/bin/m4/lib/fatal-signal.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Emergency actions in case of a fatal signal. - Copyright (C) 2003-2004 Free Software Foundation, Inc. - Written by Bruno Haible , 2003. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* It is often useful to do some cleanup action when a usually fatal signal - terminates the process, like removing a temporary file or killing a - subprocess that may be stuck waiting for a device, pipe or network input. - Such signals are SIGHUP, SIGINT, SIGPIPE, SIGTERM, and possibly others. - The limitation of this facility is that it cannot work for SIGKILL. - - Signals with a SIG_IGN handler are considered to be non-fatal. The - functions in this file assume that when a SIG_IGN handler is installed - for a signal, it was installed before any functions in this file were - called and it stays so for the whole lifetime of the process. */ - -/* Register a cleanup function to be executed when a catchable fatal signal - occurs. - - Restrictions for the cleanup function: - - The cleanup function can do all kinds of system calls. - - It can also access application dependent memory locations and data - structures provided they are in a consistent state. One way to ensure - this is through block_fatal_signals()/unblock_fatal_signals(), see - below. Another - more tricky - way to ensure this is the careful use - of 'volatile'. - However, - - malloc() and similarly complex facilities are not safe to be called - because they are not guaranteed to be in a consistent state. - - Also, the cleanup function must not block the catchable fatal signals - and leave them blocked upon return. - - The cleanup function is executed asynchronously. It is unspecified - whether during its execution the catchable fatal signals are blocked - or not. */ -extern void at_fatal_signal (void (*function) (void)); - - -/* Sometimes it is necessary to block the usually fatal signals while the - data structures being accessed by the cleanup action are being built or - reorganized. This is the case, for example, when a temporary file or - directory is created through mkstemp() or mkdtemp(), because these - functions create the temporary file or directory _before_ returning its - name to the application. */ - -/* Temporarily delay the catchable fatal signals. - The signals will be blocked (= delayed) until the next call to - unblock_fatal_signals(). If the signals are already blocked, a further - call to block_fatal_signals() has no effect. */ -extern void block_fatal_signals (void); - -/* Stop delaying the catchable fatal signals. */ -extern void unblock_fatal_signals (void); - - -#ifdef __cplusplus -} -#endif diff --git a/src/bin/m4/lib/fd-safer.c b/src/bin/m4/lib/fd-safer.c deleted file mode 100644 index 256bfa4a0e..0000000000 --- a/src/bin/m4/lib/fd-safer.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Return a safer copy of a file descriptor. - - Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include - -#include "unistd-safer.h" - -#include - -#include -#ifndef STDIN_FILENO -# define STDIN_FILENO 0 -#endif -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif - -/* Return FD, unless FD would be a copy of standard input, output, or - error; in that case, return a duplicate of FD, closing FD. On - failure to duplicate, close FD, set errno, and return -1. Preserve - errno if FD is negative, so that the caller can always inspect - errno when the returned value is negative. - - This function is usefully wrapped around functions that return file - descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */ - -int -fd_safer (int fd) -{ - if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) - { - int f = dup_safer (fd); - int e = errno; - close (fd); - errno = e; - fd = f; - } - - return fd; -} diff --git a/src/bin/m4/lib/fopen-safer.c b/src/bin/m4/lib/fopen-safer.c deleted file mode 100644 index 3502dbaa8c..0000000000 --- a/src/bin/m4/lib/fopen-safer.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Invoke fopen, but avoid some glitches. - - Copyright (C) 2001, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include - -#include "stdio-safer.h" - -#include -#include -#include "unistd-safer.h" - -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif - -/* Like fopen, but do not return stdin, stdout, or stderr. */ - -FILE * -fopen_safer (char const *file, char const *mode) -{ - FILE *fp = fopen (file, mode); - - if (fp) - { - int fd = fileno (fp); - - if (0 <= fd && fd <= STDERR_FILENO) - { - int f = dup_safer (fd); - - if (f < 0) - { - int e = errno; - fclose (fp); - errno = e; - return NULL; - } - - if (fclose (fp) != 0 - || ! (fp = fdopen (f, mode))) - { - int e = errno; - close (f); - errno = e; - return NULL; - } - } - } - - return fp; -} diff --git a/src/bin/m4/lib/free.c b/src/bin/m4/lib/free.c deleted file mode 100644 index 73a125a75f..0000000000 --- a/src/bin/m4/lib/free.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Work around incompatibility on older systems where free (NULL) fails. - - Copyright (C) 2003, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* written by Paul Eggert */ - -#include -#undef free - -#include - -void -rpl_free (void *p) -{ - if (p) - free (p); -} diff --git a/src/bin/m4/lib/getopt.c b/src/bin/m4/lib/getopt.c deleted file mode 100644 index 3580ad825c..0000000000 --- a/src/bin/m4/lib/getopt.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBC -# include -#endif - -#include "getopt.h" - -#include -#include -#include -#include - -#ifdef __VMS -# include -#endif - -#ifdef _LIBC -# include -#else -# include "gettext.h" -# define _(msgid) gettext (msgid) -#endif - -#if defined _LIBC && defined USE_IN_LIBIO -# include -#endif - -#ifndef attribute_hidden -# define attribute_hidden -#endif - -/* Unlike standard Unix `getopt', functions like `getopt_long' - let the user intersperse the options with the other arguments. - - As `getopt_long' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Using `getopt' or setting the environment variable POSIXLY_CORRECT - disables permutation. - Then the application's behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt_int.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Keep a global copy of all internal members of getopt_data. */ - -static struct _getopt_data getopt_data; - - -#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV -extern char *getenv (); -#endif - -#ifdef _LIBC -/* Stored original parameters. - XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ -extern int __libc_argc; -extern char **__libc_argv; - -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -# ifdef USE_NONOPTION_FLAGS -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; -# endif - -# ifdef USE_NONOPTION_FLAGS -# define SWAP_FLAGS(ch1, ch2) \ - if (d->__nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -# else -# define SWAP_FLAGS(ch1, ch2) -# endif -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (char **argv, struct _getopt_data *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - d->__nonoption_flags_max_len), - '\0', top + 1 - d->__nonoption_flags_max_len); - d->__nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} - -/* Initialize the internal data when the first call is made. */ - -static const char * -_getopt_initialize (int argc, char **argv, const char *optstring, - int posixly_correct, struct _getopt_data *d) -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - d->__first_nonopt = d->__last_nonopt = d->optind; - - d->__nextchar = NULL; - - d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - if (!d->__posixly_correct - && argc == __libc_argc && argv == __libc_argv) - { - if (d->__nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - d->__nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = d->__nonoption_flags_max_len = strlen (orig_str); - if (d->__nonoption_flags_max_len < argc) - d->__nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (d->__nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - d->__nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', d->__nonoption_flags_max_len - len); - } - } - d->__nonoption_flags_len = d->__nonoption_flags_max_len; - } - else - d->__nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. - - If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT - environment variable were set. */ - -int -_getopt_internal_r (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, int posixly_correct, struct _getopt_data *d) -{ - int print_errors = d->opterr; - if (optstring[0] == ':') - print_errors = 0; - - if (argc < 1) - return -1; - - d->optarg = NULL; - - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring, - posixly_correct, d); - d->__initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ - || (d->optind < d->__nonoption_flags_len \ - && __getopt_nonoption_flags[d->optind] == '1')) -#else -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') -#endif - - if (d->__nextchar == NULL || *d->__nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - - if (d->__ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (d->optind < argc && NONOPTION_P) - d->optind++; - d->__last_nonopt = d->optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (d->optind != argc && !strcmp (argv[d->optind], "--")) - { - d->optind++; - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - - d->optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (d->optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - d->__nextchar = (argv[d->optind] + 1 - + (longopts != NULL && argv[d->optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[d->optind][1] == '-' - || (long_only && (argv[d->optind][2] - || !strchr (optstring, argv[d->optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[d->optind]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - d->optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind - 1][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#else - fprintf (stderr, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#else - fprintf (stderr, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - - d->__nextchar += strlen (d->__nextchar); - - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[d->optind][1] == '-' - || strchr (optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), - argv[0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], d->__nextchar); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->__nextchar = (char *) ""; - d->optind++; - d->optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *d->__nextchar++; - char *temp = strchr (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*d->__nextchar == '\0') - ++d->optind; - - if (temp == NULL || c == ':') - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (d->__posixly_correct) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: illegal option -- %c\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); -#endif - } - else - { -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: invalid option -- %c\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, - _("%s: option requires an argument -- %c\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `d->optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; - nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[d->optind]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - - d->__nextchar += strlen (d->__nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - d->__nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option requires an argument -- %c\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} - -int -_getopt_internal (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, int posixly_correct) -{ - int result; - - getopt_data.optind = optind; - getopt_data.opterr = opterr; - - result = _getopt_internal_r (argc, argv, optstring, longopts, longind, - long_only, posixly_correct, &getopt_data); - - optind = getopt_data.optind; - optarg = getopt_data.optarg; - optopt = getopt_data.optopt; - - return result; -} - -/* glibc gets a LSB-compliant getopt. - Standalone applications get a POSIX-compliant getopt. */ -#if _LIBC -enum { POSIXLY_CORRECT = 0 }; -#else -enum { POSIXLY_CORRECT = 1 }; -#endif - -int -getopt (int argc, char *const *argv, const char *optstring) -{ - return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, - POSIXLY_CORRECT); -} - - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/src/bin/m4/lib/getopt1.c b/src/bin/m4/lib/getopt1.c deleted file mode 100644 index cc0746ea43..0000000000 --- a/src/bin/m4/lib/getopt1.c +++ /dev/null @@ -1,171 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifdef _LIBC -# include -#else -# include -# include "getopt.h" -#endif -#include "getopt_int.h" - -#include - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, - const struct option *long_options, int *opt_index) -{ - return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 0, 0); -} - -int -_getopt_long_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) -{ - return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 0, 0, d); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (int argc, char *__getopt_argv_const *argv, - const char *options, - const struct option *long_options, int *opt_index) -{ - return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 1, 0); -} - -int -_getopt_long_only_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) -{ - return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 1, 0, d); -} - - -#ifdef TEST - -#include - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/src/bin/m4/lib/getopt_.h b/src/bin/m4/lib/getopt_.h deleted file mode 100644 index 27fce3dc79..0000000000 --- a/src/bin/m4/lib/getopt_.h +++ /dev/null @@ -1,226 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GETOPT_H - -#ifndef __need_getopt -# define _GETOPT_H 1 -#endif - -/* Standalone applications should #define __GETOPT_PREFIX to an - identifier that prefixes the external functions and variables - defined in this header. When this happens, include the - headers that might declare getopt so that they will not cause - confusion if included after this file. Then systematically rename - identifiers so that they do not collide with the system functions - and variables. Renaming avoids problems with some compilers and - linkers. */ -#if defined __GETOPT_PREFIX && !defined __need_getopt -# include -# include -# include -# undef __need_getopt -# undef getopt -# undef getopt_long -# undef getopt_long_only -# undef optarg -# undef opterr -# undef optind -# undef optopt -# define __GETOPT_CONCAT(x, y) x ## y -# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) -# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) -# define getopt __GETOPT_ID (getopt) -# define getopt_long __GETOPT_ID (getopt_long) -# define getopt_long_only __GETOPT_ID (getopt_long_only) -# define optarg __GETOPT_ID (optarg) -# define opterr __GETOPT_ID (opterr) -# define optind __GETOPT_ID (optind) -# define optopt __GETOPT_ID (optopt) -#endif - -/* Standalone applications get correct prototypes for getopt_long and - getopt_long_only; they declare "char **argv". libc uses prototypes - with "char *const *argv" that are incorrect because getopt_long and - getopt_long_only can permute argv; this is required for backward - compatibility (e.g., for LSB 2.0.1). - - This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt', - but it caused redefinition warnings if both unistd.h and getopt.h were - included, since unistd.h includes getopt.h having previously defined - __need_getopt. - - The only place where __getopt_argv_const is used is in definitions - of getopt_long and getopt_long_only below, but these are visible - only if __need_getopt is not defined, so it is quite safe to rewrite - the conditional as follows: -*/ -#if !defined __need_getopt -# if defined __GETOPT_PREFIX -# define __getopt_argv_const /* empty */ -# else -# define __getopt_argv_const const -# endif -#endif - -/* If __GNU_LIBRARY__ is not already defined, either we are being used - standalone, or this is the first header included in the source file. - If we are being used with glibc, we need to include , but - that does not exist if we are standalone. So: if __GNU_LIBRARY__ is - not defined, include , which will pull in for us - if it's from glibc. (Why ctype.h? It's guaranteed to exist and it - doesn't flood the namespace with stuff the way some other headers do.) */ -#if !defined __GNU_LIBRARY__ -# include -#endif - -#ifndef __THROW -# ifndef __GNUC_PREREQ -# define __GNUC_PREREQ(maj, min) (0) -# endif -# if defined __cplusplus && __GNUC_PREREQ (2,8) -# define __THROW throw () -# else -# define __THROW -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -#ifndef __need_getopt -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ - const char *name; - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - - -/* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, `optopt' is set to the option letter, and '?' is - returned. - - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in `optarg'. - - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU `getopt'. - - The argument `--' causes premature termination of argument - scanning, explicitly telling `getopt' that there are no more - options. - - If OPTS begins with `-', then non-option arguments are treated as - arguments to the option '\1'. This behavior is specific to the GNU - `getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in - the environment, then do not permute arguments. */ - -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) - __THROW; - -#ifndef __need_getopt -extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW; -extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW; - -#endif - -#ifdef __cplusplus -} -#endif - -/* Make sure we later can get all the definitions and declarations. */ -#undef __need_getopt - -#endif /* getopt.h */ diff --git a/src/bin/m4/lib/getopt_int.h b/src/bin/m4/lib/getopt_int.h deleted file mode 100644 index 401579fd28..0000000000 --- a/src/bin/m4/lib/getopt_int.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Internal declarations for getopt. - Copyright (C) 1989-1994,1996-1999,2001,2003,2004 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GETOPT_INT_H -#define _GETOPT_INT_H 1 - -extern int _getopt_internal (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct); - - -/* Reentrant versions which can handle parsing multiple argument - vectors at the same time. */ - -/* Data type for reentrant functions. */ -struct _getopt_data -{ - /* These have exactly the same meaning as the corresponding global - variables, except that they are used for the reentrant - versions of getopt. */ - int optind; - int opterr; - int optopt; - char *optarg; - - /* Internal members. */ - - /* True if the internal members have been initialized. */ - int __initialized; - - /* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - char *__nextchar; - - /* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - - enum - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - } __ordering; - - /* If the POSIXLY_CORRECT environment variable is set - or getopt was called. */ - int __posixly_correct; - - - /* Handle permutation of arguments. */ - - /* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first - of them; `last_nonopt' is the index after the last of them. */ - - int __first_nonopt; - int __last_nonopt; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - int __nonoption_flags_max_len; - int __nonoption_flags_len; -# endif -}; - -/* The initializer is necessary to set OPTIND and OPTERR to their - default values and to clear the initialization flag. */ -#define _GETOPT_DATA_INITIALIZER { 1, 1 } - -extern int _getopt_internal_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct, - struct _getopt_data *__data); - -extern int _getopt_long_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - struct _getopt_data *__data); - -extern int _getopt_long_only_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, - int *__longind, - struct _getopt_data *__data); - -#endif /* getopt_int.h */ diff --git a/src/bin/m4/lib/gettext.h b/src/bin/m4/lib/gettext.h deleted file mode 100644 index 18c62a4067..0000000000 --- a/src/bin/m4/lib/gettext.h +++ /dev/null @@ -1,269 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000-2002, 2004-2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by - the gettext() and ngettext() macros. This is an alternative to calling - textdomain(), and is useful for libraries. */ -# ifdef DEFAULT_TEXT_DOMAIN -# undef gettext -# define gettext(Msgid) \ - dgettext (DEFAULT_TEXT_DOMAIN, Msgid) -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) -# endif - -#else - -/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which - chokes if dcgettext is defined as a macro. So include it now, to make - later inclusions of a NOP. We don't include - as well because people using "gettext.h" will not include , - and also including would fail on SunOS 4, whereas - is OK. */ -#if defined(__sun) -# include -#endif - -/* Many header files from the libstdc++ coming with g++ 3.3 or newer include - , which chokes if dcgettext is defined as a macro. So include - it now, to make later inclusions of a NOP. */ -#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) -# include -# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H -# include -# endif -#endif - -/* Disabled NLS. - The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. - On pre-ANSI systems without 'const', the config.h file is supposed to - contain "#define const". */ -# define gettext(Msgid) ((const char *) (Msgid)) -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) -# define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) -# define textdomain(Domainname) ((const char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) \ - ((void) (Domainname), (const char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (Domainname), (const char *) (Codeset)) - -#endif - -/* A pseudo function call that serves as a marker for the automated - extraction of messages, but does not call gettext(). The run-time - translation is done at a different place in the code. - The argument, String, should be a literal string. Concatenated strings - and other string expressions won't work. - The macro's expansion is not parenthesized, so that it is suitable as - initializer for static 'char[]' or 'const char[]' variables. */ -#define gettext_noop(String) String - -/* The separator between msgctxt and msgid in a .mo file. */ -#define GETTEXT_CONTEXT_GLUE "\004" - -/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a - MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be - short and rarely need to change. - The letter 'p' stands for 'particular' or 'special'. */ -#ifdef DEFAULT_TEXT_DOMAIN -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#else -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#endif -#define dpgettext(Domainname, Msgctxt, Msgid) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) -#ifdef DEFAULT_TEXT_DOMAIN -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#else -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#endif -#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -pgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - int category) -{ - const char *translation = dcgettext (domain, msg_ctxt_id, category); - if (translation == msg_ctxt_id) - return msgid; - else - return translation; -} - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -npgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - const char *translation = - dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); - if (translation == msg_ctxt_id || translation == msgid_plural) - return (n == 1 ? msgid : msgid_plural); - else - return translation; -} - -/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID - can be arbitrary expressions. But for string literals these macros are - less efficient than those above. */ - -#include - -#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ - (__GNUC__ >= 3 || __GNUG__ >= 2 /* || __STDC_VERSION__ >= 199901L */ ) - -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS -#include -#endif - -#define pgettext_expr(Msgctxt, Msgid) \ - dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) -#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ - dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcgettext (domain, msg_ctxt_id, category); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (translation != msg_ctxt_id) - return translation; - } - return msgid; -} - -#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcnpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (!(translation == msg_ctxt_id || translation == msgid_plural)) - return translation; - } - return (n == 1 ? msgid : msgid_plural); -} - -#endif /* _LIBGETTEXT_H */ diff --git a/src/bin/m4/lib/gl_anyhash_list1.h b/src/bin/m4/lib/gl_anyhash_list1.h deleted file mode 100644 index 1f1351e7ac..0000000000 --- a/src/bin/m4/lib/gl_anyhash_list1.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Sequential list data type implemented by a hash table with another list. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Common code of - gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c. */ - -/* Hash table entry. */ -struct gl_hash_entry -{ - struct gl_hash_entry *hash_next; /* chain of entries in same bucket */ - size_t hashcode; /* cache of values' common hash code */ -}; -typedef struct gl_hash_entry * gl_hash_entry_t; diff --git a/src/bin/m4/lib/gl_anyhash_list2.h b/src/bin/m4/lib/gl_anyhash_list2.h deleted file mode 100644 index d719116866..0000000000 --- a/src/bin/m4/lib/gl_anyhash_list2.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Sequential list data type implemented by a hash table with another list. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Common code of - gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c. */ - -/* Array of primes, approximately in steps of factor 1.2. - This table was computed by executing the Common Lisp expression - (dotimes (i 244) (format t "nextprime(~D)~%" (ceiling (expt 1.2d0 i)))) - and feeding the result to PARI/gp. */ -static const size_t primes[] = - { - 11, 13, 17, 19, 23, 29, 37, 41, 47, 59, 67, 83, 97, 127, 139, 167, 199, - 239, 293, 347, 419, 499, 593, 709, 853, 1021, 1229, 1471, 1777, 2129, 2543, - 3049, 3659, 4391, 5273, 6323, 7589, 9103, 10937, 13109, 15727, 18899, - 22651, 27179, 32609, 39133, 46957, 56359, 67619, 81157, 97369, 116849, - 140221, 168253, 201907, 242309, 290761, 348889, 418667, 502409, 602887, - 723467, 868151, 1041779, 1250141, 1500181, 1800191, 2160233, 2592277, - 3110741, 3732887, 4479463, 5375371, 6450413, 7740517, 9288589, 11146307, - 13375573, 16050689, 19260817, 23112977, 27735583, 33282701, 39939233, - 47927081, 57512503, 69014987, 82818011, 99381577, 119257891, 143109469, - 171731387, 206077643, 247293161, 296751781, 356102141, 427322587, - 512787097, 615344489, 738413383, 886096061, 1063315271, 1275978331, - 1531174013, 1837408799, 2204890543UL, 2645868653UL, 3175042391UL, - 3810050851UL, -#if SIZE_MAX > 4294967295UL - 4572061027UL, 5486473229UL, 6583767889UL, 7900521449UL, 9480625733UL, - 11376750877UL, 13652101063UL, 16382521261UL, 19659025513UL, 23590830631UL, - 28308996763UL, 33970796089UL, 40764955463UL, 48917946377UL, 58701535657UL, - 70441842749UL, 84530211301UL, 101436253561UL, 121723504277UL, - 146068205131UL, 175281846149UL, 210338215379UL, 252405858521UL, - 302887030151UL, 363464436191UL, 436157323417UL, 523388788231UL, - 628066545713UL, 753679854847UL, 904415825857UL, 1085298991109UL, - 1302358789181UL, 1562830547009UL, 1875396656429UL, 2250475987709UL, - 2700571185239UL, 3240685422287UL, 3888822506759UL, 4666587008147UL, - 5599904409713UL, 6719885291641UL, 8063862349969UL, 9676634819959UL, - 11611961783951UL, 13934354140769UL, 16721224968907UL, 20065469962669UL, - 24078563955191UL, 28894276746229UL, 34673132095507UL, 41607758514593UL, - 49929310217531UL, 59915172260971UL, 71898206713183UL, 86277848055823UL, - 103533417666967UL, 124240101200359UL, 149088121440451UL, 178905745728529UL, - 214686894874223UL, 257624273849081UL, 309149128618903UL, 370978954342639UL, - 445174745211143UL, 534209694253381UL, 641051633104063UL, 769261959724877UL, - 923114351670013UL, 1107737222003791UL, 1329284666404567UL, - 1595141599685509UL, 1914169919622551UL, 2297003903547091UL, - 2756404684256459UL, 3307685621107757UL, 3969222745329323UL, - 4763067294395177UL, 5715680753274209UL, 6858816903929113UL, - 8230580284714831UL, 9876696341657791UL, 11852035609989371UL, - 14222442731987227UL, 17066931278384657UL, 20480317534061597UL, - 24576381040873903UL, 29491657249048679UL, 35389988698858471UL, - 42467986438630267UL, 50961583726356109UL, 61153900471627387UL, - 73384680565952851UL, 88061616679143347UL, 105673940014972061UL, - 126808728017966413UL, 152170473621559703UL, 182604568345871671UL, - 219125482015045997UL, 262950578418055169UL, 315540694101666193UL, - 378648832921999397UL, 454378599506399233UL, 545254319407679131UL, - 654305183289214771UL, 785166219947057701UL, 942199463936469157UL, - 1130639356723763129UL, 1356767228068515623UL, 1628120673682218619UL, - 1953744808418662409UL, 2344493770102394881UL, 2813392524122873857UL, - 3376071028947448339UL, 4051285234736937517UL, 4861542281684325481UL, - 5833850738021191727UL, 7000620885625427969UL, 8400745062750513217UL, - 10080894075300616261UL, 12097072890360739951UL, 14516487468432885797UL, - 17419784962119465179UL, -#endif - SIZE_MAX /* sentinel, to ensure the search terminates */ - }; - -/* Return a suitable prime >= ESTIMATE. */ -static size_t -next_prime (size_t estimate) -{ - size_t i; - - for (i = 0; i < sizeof (primes) / sizeof (primes[0]); i++) - if (primes[i] >= estimate) - return primes[i]; - return SIZE_MAX; /* not a prime, but better than nothing */ -} - -/* Resize the hash table with a new estimated size. */ -static void -hash_resize (gl_list_t list, size_t estimate) -{ - size_t new_size = next_prime (estimate); - - if (new_size > list->table_size) - { - gl_hash_entry_t *old_table = list->table; - /* Allocate the new table. */ - gl_hash_entry_t *new_table = XCALLOC (new_size, gl_hash_entry_t); - size_t i; - - /* Iterate through the entries of the old table. */ - for (i = list->table_size; i > 0; ) - { - gl_hash_entry_t node = old_table[--i]; - - while (node != NULL) - { - gl_hash_entry_t next = node->hash_next; - /* Add the entry to the new table. */ - size_t bucket = node->hashcode % new_size; - node->hash_next = new_table[bucket]; - new_table[bucket] = node; - - node = next; - } - } - - list->table = new_table; - list->table_size = new_size; - free (old_table); - } -} diff --git a/src/bin/m4/lib/gl_anylinked_list1.h b/src/bin/m4/lib/gl_anylinked_list1.h deleted file mode 100644 index 988657e5c4..0000000000 --- a/src/bin/m4/lib/gl_anylinked_list1.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Sequential list data type implemented by a linked list. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Common code of gl_linked_list.c and gl_linkedhash_list.c. */ - -/* -------------------------- gl_list_t Data Type -------------------------- */ - -/* Concrete list node implementation, valid for this file only. */ -struct gl_list_node_impl -{ -#if WITH_HASHTABLE - struct gl_hash_entry h; /* hash table entry fields; must be first */ -#endif - struct gl_list_node_impl *next; - struct gl_list_node_impl *prev; - const void *value; -}; - -/* Concrete gl_list_impl type, valid for this file only. */ -struct gl_list_impl -{ - struct gl_list_impl_base base; -#if WITH_HASHTABLE - /* A hash table: managed as an array of collision lists. */ - struct gl_hash_entry **table; - size_t table_size; -#endif - /* A circular list anchored at root. - The first node is = root.next, the last node is = root.prev. - The root's value is unused. */ - struct gl_list_node_impl root; - /* Number of list nodes, excluding the root. */ - size_t count; -}; diff --git a/src/bin/m4/lib/gl_anylinked_list2.h b/src/bin/m4/lib/gl_anylinked_list2.h deleted file mode 100644 index 718dfb713a..0000000000 --- a/src/bin/m4/lib/gl_anylinked_list2.h +++ /dev/null @@ -1,1045 +0,0 @@ -/* Sequential list data type implemented by a linked list. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Common code of gl_linked_list.c and gl_linkedhash_list.c. */ - -/* If the symbol SIGNAL_SAFE_LIST is defined, the code is compiled in such - a way that a gl_list_t data structure may be used from within a signal - handler. The operations allowed in the signal handler are: - gl_list_iterator, gl_list_iterator_next, gl_list_iterator_free. - The list and node fields that are therefore accessed from the signal handler - are: - list->root, node->next, node->value. - We are careful to make modifications to these fields only in an order - that maintains the consistency of the list data structure at any moment, - and we use 'volatile' assignments to prevent the compiler from reordering - such assignments. */ -#ifdef SIGNAL_SAFE_LIST -# define ASYNCSAFE(type) *(volatile type *)& -#else -# define ASYNCSAFE(type) -#endif - -/* -------------------------- gl_list_t Data Type -------------------------- */ - -static gl_list_t -gl_linked_create_empty (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates) -{ - struct gl_list_impl *list = XMALLOC (struct gl_list_impl); - - list->base.vtable = implementation; - list->base.equals_fn = equals_fn; - list->base.hashcode_fn = hashcode_fn; - list->base.allow_duplicates = allow_duplicates; -#if WITH_HASHTABLE - list->table_size = 11; - list->table = XCALLOC (list->table_size, gl_hash_entry_t); -#endif - list->root.next = &list->root; - list->root.prev = &list->root; - list->count = 0; - - return list; -} - -static gl_list_t -gl_linked_create (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates, - size_t count, const void **contents) -{ - struct gl_list_impl *list = XMALLOC (struct gl_list_impl); - gl_list_node_t tail; - - list->base.vtable = implementation; - list->base.equals_fn = equals_fn; - list->base.hashcode_fn = hashcode_fn; - list->base.allow_duplicates = allow_duplicates; -#if WITH_HASHTABLE - { - size_t estimate = xsum (count, count / 2); /* 1.5 * count */ - if (estimate < 10) - estimate = 10; - list->table_size = next_prime (estimate); - list->table = XCALLOC (list->table_size, gl_hash_entry_t); - } -#endif - list->count = count; - tail = &list->root; - for (; count > 0; contents++, count--) - { - gl_list_node_t node = XMALLOC (struct gl_list_node_impl); - - node->value = *contents; -#if WITH_HASHTABLE - node->h.hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (node->value) - : (size_t)(uintptr_t) node->value); - - /* Add node to the hash table. */ - add_to_bucket (list, node); -#endif - - /* Add node to the list. */ - node->prev = tail; - tail->next = node; - tail = node; - } - tail->next = &list->root; - list->root.prev = tail; - - return list; -} - -static size_t -gl_linked_size (gl_list_t list) -{ - return list->count; -} - -static const void * -gl_linked_node_value (gl_list_t list, gl_list_node_t node) -{ - return node->value; -} - -static gl_list_node_t -gl_linked_next_node (gl_list_t list, gl_list_node_t node) -{ - return (node->next != &list->root ? node->next : NULL); -} - -static gl_list_node_t -gl_linked_previous_node (gl_list_t list, gl_list_node_t node) -{ - return (node->prev != &list->root ? node->prev : NULL); -} - -static const void * -gl_linked_get_at (gl_list_t list, size_t position) -{ - size_t count = list->count; - gl_list_node_t node; - - if (!(position < count)) - /* Invalid argument. */ - abort (); - /* Here we know count > 0. */ - if (position <= ((count - 1) / 2)) - { - node = list->root.next; - for (; position > 0; position--) - node = node->next; - } - else - { - position = count - 1 - position; - node = list->root.prev; - for (; position > 0; position--) - node = node->prev; - } - return node->value; -} - -static gl_list_node_t -gl_linked_set_at (gl_list_t list, size_t position, const void *elt) -{ - size_t count = list->count; - gl_list_node_t node; - - if (!(position < count)) - /* Invalid argument. */ - abort (); - /* Here we know count > 0. */ - if (position <= ((count - 1) / 2)) - { - node = list->root.next; - for (; position > 0; position--) - node = node->next; - } - else - { - position = count - 1 - position; - node = list->root.prev; - for (; position > 0; position--) - node = node->prev; - } -#if WITH_HASHTABLE - if (elt != node->value) - { - size_t new_hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (elt) - : (size_t)(uintptr_t) elt); - - if (new_hashcode != node->h.hashcode) - { - remove_from_bucket (list, node); - node->value = elt; - node->h.hashcode = new_hashcode; - add_to_bucket (list, node); - } - else - node->value = elt; - } -#else - node->value = elt; -#endif - return node; -} - -static gl_list_node_t -gl_linked_search_from_to (gl_list_t list, size_t start_index, size_t end_index, - const void *elt) -{ - size_t count = list->count; - - if (!(start_index <= end_index && end_index <= count)) - /* Invalid arguments. */ - abort (); - { -#if WITH_HASHTABLE - size_t hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (elt) - : (size_t)(uintptr_t) elt); - size_t bucket = hashcode % list->table_size; - gl_listelement_equals_fn equals = list->base.equals_fn; - - if (!list->base.allow_duplicates) - { - /* Look for the first match in the hash bucket. */ - gl_list_node_t found = NULL; - gl_list_node_t node; - - for (node = (gl_list_node_t) list->table[bucket]; - node != NULL; - node = (gl_list_node_t) node->h.hash_next) - if (node->h.hashcode == hashcode - && (equals != NULL - ? equals (elt, node->value) - : elt == node->value)) - { - found = node; - break; - } - if (start_index > 0) - /* Look whether found's index is < start_index. */ - for (node = list->root.next; ; node = node->next) - { - if (node == found) - return NULL; - if (--start_index == 0) - break; - } - if (end_index < count) - /* Look whether found's index is >= end_index. */ - { - end_index = count - end_index; - for (node = list->root.prev; ; node = node->prev) - { - if (node == found) - return NULL; - if (--end_index == 0) - break; - } - } - return found; - } - else - { - /* Look whether there is more than one match in the hash bucket. */ - bool multiple_matches = false; - gl_list_node_t first_match = NULL; - gl_list_node_t node; - - for (node = (gl_list_node_t) list->table[bucket]; - node != NULL; - node = (gl_list_node_t) node->h.hash_next) - if (node->h.hashcode == hashcode - && (equals != NULL - ? equals (elt, node->value) - : elt == node->value)) - { - if (first_match == NULL) - first_match = node; - else - { - multiple_matches = true; - break; - } - } - if (multiple_matches) - { - /* We need the match with the smallest index. But we don't have - a fast mapping node -> index. So we have to walk the list. */ - end_index -= start_index; - node = list->root.next; - for (; start_index > 0; start_index--) - node = node->next; - - for (; - end_index > 0; - node = node->next, end_index--) - if (node->h.hashcode == hashcode - && (equals != NULL - ? equals (elt, node->value) - : elt == node->value)) - return node; - /* The matches must have all been at indices < start_index or - >= end_index. */ - return NULL; - } - else - { - if (start_index > 0) - /* Look whether first_match's index is < start_index. */ - for (node = list->root.next; node != &list->root; node = node->next) - { - if (node == first_match) - return NULL; - if (--start_index == 0) - break; - } - if (end_index < list->count) - /* Look whether first_match's index is >= end_index. */ - { - end_index = list->count - end_index; - for (node = list->root.prev; ; node = node->prev) - { - if (node == first_match) - return NULL; - if (--end_index == 0) - break; - } - } - return first_match; - } - } -#else - gl_listelement_equals_fn equals = list->base.equals_fn; - gl_list_node_t node = list->root.next; - - end_index -= start_index; - for (; start_index > 0; start_index--) - node = node->next; - - if (equals != NULL) - { - for (; end_index > 0; node = node->next, end_index--) - if (equals (elt, node->value)) - return node; - } - else - { - for (; end_index > 0; node = node->next, end_index--) - if (elt == node->value) - return node; - } - return NULL; -#endif - } -} - -static size_t -gl_linked_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, - const void *elt) -{ - size_t count = list->count; - - if (!(start_index <= end_index && end_index <= count)) - /* Invalid arguments. */ - abort (); - { -#if WITH_HASHTABLE - /* Here the hash table doesn't help much. It only allows us to minimize - the number of equals() calls, by looking up first the node and then - its index. */ - size_t hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (elt) - : (size_t)(uintptr_t) elt); - size_t bucket = hashcode % list->table_size; - gl_listelement_equals_fn equals = list->base.equals_fn; - gl_list_node_t node; - - /* First step: Look up the node. */ - if (!list->base.allow_duplicates) - { - /* Look for the first match in the hash bucket. */ - for (node = (gl_list_node_t) list->table[bucket]; - node != NULL; - node = (gl_list_node_t) node->h.hash_next) - if (node->h.hashcode == hashcode - && (equals != NULL - ? equals (elt, node->value) - : elt == node->value)) - break; - } - else - { - /* Look whether there is more than one match in the hash bucket. */ - bool multiple_matches = false; - gl_list_node_t first_match = NULL; - - for (node = (gl_list_node_t) list->table[bucket]; - node != NULL; - node = (gl_list_node_t) node->h.hash_next) - if (node->h.hashcode == hashcode - && (equals != NULL - ? equals (elt, node->value) - : elt == node->value)) - { - if (first_match == NULL) - first_match = node; - else - { - multiple_matches = true; - break; - } - } - if (multiple_matches) - { - /* We need the match with the smallest index. But we don't have - a fast mapping node -> index. So we have to walk the list. */ - size_t index; - - index = start_index; - node = list->root.next; - for (; start_index > 0; start_index--) - node = node->next; - - for (; - index < end_index; - node = node->next, index++) - if (node->h.hashcode == hashcode - && (equals != NULL - ? equals (elt, node->value) - : elt == node->value)) - return index; - /* The matches must have all been at indices < start_index or - >= end_index. */ - return (size_t)(-1); - } - node = first_match; - } - - /* Second step: Look up the index of the node. */ - if (node == NULL) - return (size_t)(-1); - else - { - size_t index = 0; - - for (; node->prev != &list->root; node = node->prev) - index++; - - if (index >= start_index && index < end_index) - return index; - else - return (size_t)(-1); - } -#else - gl_listelement_equals_fn equals = list->base.equals_fn; - size_t index = start_index; - gl_list_node_t node = list->root.next; - - for (; start_index > 0; start_index--) - node = node->next; - - if (equals != NULL) - { - for (; - index < end_index; - node = node->next, index++) - if (equals (elt, node->value)) - return index; - } - else - { - for (; - index < end_index; - node = node->next, index++) - if (elt == node->value) - return index; - } - return (size_t)(-1); -#endif - } -} - -static gl_list_node_t -gl_linked_add_first (gl_list_t list, const void *elt) -{ - gl_list_node_t node = XMALLOC (struct gl_list_node_impl); - - ASYNCSAFE(const void *) node->value = elt; -#if WITH_HASHTABLE - node->h.hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (node->value) - : (size_t)(uintptr_t) node->value); - - /* Add node to the hash table. */ - add_to_bucket (list, node); -#endif - - /* Add node to the list. */ - node->prev = &list->root; - ASYNCSAFE(gl_list_node_t) node->next = list->root.next; - node->next->prev = node; - ASYNCSAFE(gl_list_node_t) list->root.next = node; - list->count++; - -#if WITH_HASHTABLE - hash_resize_after_add (list); -#endif - - return node; -} - -static gl_list_node_t -gl_linked_add_last (gl_list_t list, const void *elt) -{ - gl_list_node_t node = XMALLOC (struct gl_list_node_impl); - - ASYNCSAFE(const void *) node->value = elt; -#if WITH_HASHTABLE - node->h.hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (node->value) - : (size_t)(uintptr_t) node->value); - - /* Add node to the hash table. */ - add_to_bucket (list, node); -#endif - - /* Add node to the list. */ - ASYNCSAFE(gl_list_node_t) node->next = &list->root; - node->prev = list->root.prev; - ASYNCSAFE(gl_list_node_t) node->prev->next = node; - list->root.prev = node; - list->count++; - -#if WITH_HASHTABLE - hash_resize_after_add (list); -#endif - - return node; -} - -static gl_list_node_t -gl_linked_add_before (gl_list_t list, gl_list_node_t node, const void *elt) -{ - gl_list_node_t new_node = XMALLOC (struct gl_list_node_impl); - - ASYNCSAFE(const void *) new_node->value = elt; -#if WITH_HASHTABLE - new_node->h.hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (new_node->value) - : (size_t)(uintptr_t) new_node->value); - - /* Add new_node to the hash table. */ - add_to_bucket (list, new_node); -#endif - - /* Add new_node to the list. */ - ASYNCSAFE(gl_list_node_t) new_node->next = node; - new_node->prev = node->prev; - ASYNCSAFE(gl_list_node_t) new_node->prev->next = new_node; - node->prev = new_node; - list->count++; - -#if WITH_HASHTABLE - hash_resize_after_add (list); -#endif - - return new_node; -} - -static gl_list_node_t -gl_linked_add_after (gl_list_t list, gl_list_node_t node, const void *elt) -{ - gl_list_node_t new_node = XMALLOC (struct gl_list_node_impl); - - ASYNCSAFE(const void *) new_node->value = elt; -#if WITH_HASHTABLE - new_node->h.hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (new_node->value) - : (size_t)(uintptr_t) new_node->value); - - /* Add new_node to the hash table. */ - add_to_bucket (list, new_node); -#endif - - /* Add new_node to the list. */ - new_node->prev = node; - ASYNCSAFE(gl_list_node_t) new_node->next = node->next; - new_node->next->prev = new_node; - ASYNCSAFE(gl_list_node_t) node->next = new_node; - list->count++; - -#if WITH_HASHTABLE - hash_resize_after_add (list); -#endif - - return new_node; -} - -static gl_list_node_t -gl_linked_add_at (gl_list_t list, size_t position, const void *elt) -{ - size_t count = list->count; - gl_list_node_t new_node; - - if (!(position <= count)) - /* Invalid argument. */ - abort (); - - new_node = XMALLOC (struct gl_list_node_impl); - ASYNCSAFE(const void *) new_node->value = elt; -#if WITH_HASHTABLE - new_node->h.hashcode = - (list->base.hashcode_fn != NULL - ? list->base.hashcode_fn (new_node->value) - : (size_t)(uintptr_t) new_node->value); - - /* Add new_node to the hash table. */ - add_to_bucket (list, new_node); -#endif - - /* Add new_node to the list. */ - if (position <= (count / 2)) - { - gl_list_node_t node; - - node = &list->root; - for (; position > 0; position--) - node = node->next; - new_node->prev = node; - ASYNCSAFE(gl_list_node_t) new_node->next = node->next; - new_node->next->prev = new_node; - ASYNCSAFE(gl_list_node_t) node->next = new_node; - } - else - { - gl_list_node_t node; - - position = count - position; - node = &list->root; - for (; position > 0; position--) - node = node->prev; - ASYNCSAFE(gl_list_node_t) new_node->next = node; - new_node->prev = node->prev; - ASYNCSAFE(gl_list_node_t) new_node->prev->next = new_node; - node->prev = new_node; - } - list->count++; - -#if WITH_HASHTABLE - hash_resize_after_add (list); -#endif - - return new_node; -} - -static bool -gl_linked_remove_node (gl_list_t list, gl_list_node_t node) -{ - gl_list_node_t prev; - gl_list_node_t next; - -#if WITH_HASHTABLE - /* Remove node from the hash table. */ - remove_from_bucket (list, node); -#endif - - /* Remove node from the list. */ - prev = node->prev; - next = node->next; - - ASYNCSAFE(gl_list_node_t) prev->next = next; - next->prev = prev; - list->count--; - - free (node); - return true; -} - -static bool -gl_linked_remove_at (gl_list_t list, size_t position) -{ - size_t count = list->count; - gl_list_node_t removed_node; - - if (!(position < count)) - /* Invalid argument. */ - abort (); - /* Here we know count > 0. */ - if (position <= ((count - 1) / 2)) - { - gl_list_node_t node; - gl_list_node_t after_removed; - - node = &list->root; - for (; position > 0; position--) - node = node->next; - removed_node = node->next; - after_removed = node->next->next; - ASYNCSAFE(gl_list_node_t) node->next = after_removed; - after_removed->prev = node; - } - else - { - gl_list_node_t node; - gl_list_node_t before_removed; - - position = count - 1 - position; - node = &list->root; - for (; position > 0; position--) - node = node->prev; - removed_node = node->prev; - before_removed = node->prev->prev; - node->prev = before_removed; - ASYNCSAFE(gl_list_node_t) before_removed->next = node; - } -#if WITH_HASHTABLE - remove_from_bucket (list, removed_node); -#endif - list->count--; - - free (removed_node); - return true; -} - -static bool -gl_linked_remove (gl_list_t list, const void *elt) -{ - gl_list_node_t node = gl_linked_search_from_to (list, 0, list->count, elt); - - if (node != NULL) - return gl_linked_remove_node (list, node); - else - return false; -} - -static void -gl_linked_list_free (gl_list_t list) -{ - gl_list_node_t node; - - for (node = list->root.next; node != &list->root; ) - { - gl_list_node_t next = node->next; - free (node); - node = next; - } -#if WITH_HASHTABLE - free (list->table); -#endif - free (list); -} - -/* --------------------- gl_list_iterator_t Data Type --------------------- */ - -static gl_list_iterator_t -gl_linked_iterator (gl_list_t list) -{ - gl_list_iterator_t result; - - result.vtable = list->base.vtable; - result.list = list; - result.p = list->root.next; - result.q = &list->root; -#ifdef lint - result.i = 0; - result.j = 0; - result.count = 0; -#endif - - return result; -} - -static gl_list_iterator_t -gl_linked_iterator_from_to (gl_list_t list, - size_t start_index, size_t end_index) -{ - gl_list_iterator_t result; - size_t n1, n2, n3; - - if (!(start_index <= end_index && end_index <= list->count)) - /* Invalid arguments. */ - abort (); - result.vtable = list->base.vtable; - result.list = list; - n1 = start_index; - n2 = end_index - start_index; - n3 = list->count - end_index; - /* Find the maximum among n1, n2, n3, so as to reduce the number of - loop iterations to n1 + n2 + n3 - max(n1,n2,n3). */ - if (n1 > n2 && n1 > n3) - { - /* n1 is the maximum, use n2 and n3. */ - gl_list_node_t node; - size_t i; - - node = &list->root; - for (i = n3; i > 0; i--) - node = node->prev; - result.q = node; - for (i = n2; i > 0; i--) - node = node->prev; - result.p = node; - } - else if (n2 > n3) - { - /* n2 is the maximum, use n1 and n3. */ - gl_list_node_t node; - size_t i; - - node = list->root.next; - for (i = n1; i > 0; i--) - node = node->next; - result.p = node; - - node = &list->root; - for (i = n3; i > 0; i--) - node = node->prev; - result.q = node; - } - else - { - /* n3 is the maximum, use n1 and n2. */ - gl_list_node_t node; - size_t i; - - node = list->root.next; - for (i = n1; i > 0; i--) - node = node->next; - result.p = node; - for (i = n2; i > 0; i--) - node = node->next; - result.q = node; - } - -#ifdef lint - result.i = 0; - result.j = 0; - result.count = 0; -#endif - - return result; -} - -static bool -gl_linked_iterator_next (gl_list_iterator_t *iterator, - const void **eltp, gl_list_node_t *nodep) -{ - if (iterator->p != iterator->q) - { - gl_list_node_t node = (gl_list_node_t) iterator->p; - *eltp = node->value; - if (nodep != NULL) - *nodep = node; - iterator->p = node->next; - return true; - } - else - return false; -} - -static void -gl_linked_iterator_free (gl_list_iterator_t *iterator) -{ -} - -/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ - -static gl_list_node_t -gl_linked_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, - const void *elt) -{ - gl_list_node_t node; - - for (node = list->root.next; node != &list->root; node = node->next) - { - int cmp = compar (node->value, elt); - - if (cmp > 0) - break; - if (cmp == 0) - return node; - } - return NULL; -} - -static gl_list_node_t -gl_linked_sortedlist_search_from_to (gl_list_t list, - gl_listelement_compar_fn compar, - size_t low, size_t high, - const void *elt) -{ - size_t count = list->count; - - if (!(low <= high && high <= list->count)) - /* Invalid arguments. */ - abort (); - - high -= low; - if (high > 0) - { - /* Here we know low < count. */ - size_t position = low; - gl_list_node_t node; - - if (position <= ((count - 1) / 2)) - { - node = list->root.next; - for (; position > 0; position--) - node = node->next; - } - else - { - position = count - 1 - position; - node = list->root.prev; - for (; position > 0; position--) - node = node->prev; - } - - do - { - int cmp = compar (node->value, elt); - - if (cmp > 0) - break; - if (cmp == 0) - return node; - node = node->next; - } - while (--high > 0); - } - return NULL; -} - -static size_t -gl_linked_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, - const void *elt) -{ - gl_list_node_t node; - size_t index; - - for (node = list->root.next, index = 0; - node != &list->root; - node = node->next, index++) - { - int cmp = compar (node->value, elt); - - if (cmp > 0) - break; - if (cmp == 0) - return index; - } - return (size_t)(-1); -} - -static size_t -gl_linked_sortedlist_indexof_from_to (gl_list_t list, - gl_listelement_compar_fn compar, - size_t low, size_t high, - const void *elt) -{ - size_t count = list->count; - - if (!(low <= high && high <= list->count)) - /* Invalid arguments. */ - abort (); - - high -= low; - if (high > 0) - { - /* Here we know low < count. */ - size_t index = low; - size_t position = low; - gl_list_node_t node; - - if (position <= ((count - 1) / 2)) - { - node = list->root.next; - for (; position > 0; position--) - node = node->next; - } - else - { - position = count - 1 - position; - node = list->root.prev; - for (; position > 0; position--) - node = node->prev; - } - - do - { - int cmp = compar (node->value, elt); - - if (cmp > 0) - break; - if (cmp == 0) - return index; - node = node->next; - index++; - } - while (--high > 0); - } - return (size_t)(-1); -} - -static gl_list_node_t -gl_linked_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar, - const void *elt) -{ - gl_list_node_t node; - - for (node = list->root.next; node != &list->root; node = node->next) - if (compar (node->value, elt) >= 0) - return gl_linked_add_before (list, node, elt); - return gl_linked_add_last (list, elt); -} - -static bool -gl_linked_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, - const void *elt) -{ - gl_list_node_t node; - - for (node = list->root.next; node != &list->root; node = node->next) - { - int cmp = compar (node->value, elt); - - if (cmp > 0) - break; - if (cmp == 0) - return gl_linked_remove_node (list, node); - } - return false; -} diff --git a/src/bin/m4/lib/gl_anytree_oset.h b/src/bin/m4/lib/gl_anytree_oset.h deleted file mode 100644 index b6b50b4bc9..0000000000 --- a/src/bin/m4/lib/gl_anytree_oset.h +++ /dev/null @@ -1,287 +0,0 @@ -/* Ordered set data type implemented by a binary tree. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Common code of gl_avltree_oset.c and gl_rbtree_oset.c. */ - -/* An item on the stack used for iterating across the elements. */ -typedef struct -{ - gl_oset_node_t node; - bool rightp; -} iterstack_item_t; - -/* A stack used for iterating across the elements. */ -typedef iterstack_item_t iterstack_t[MAXHEIGHT]; - -static gl_oset_t -gl_tree_create_empty (gl_oset_implementation_t implementation, - gl_setelement_compar_fn compar_fn) -{ - struct gl_oset_impl *set = XMALLOC (struct gl_oset_impl); - - set->base.vtable = implementation; - set->base.compar_fn = compar_fn; - set->root = NULL; - set->count = 0; - - return set; -} - -static size_t -gl_tree_size (gl_oset_t set) -{ - return set->count; -} - -static bool -gl_tree_search (gl_oset_t set, const void *elt) -{ - gl_setelement_compar_fn compar = set->base.compar_fn; - gl_oset_node_t node; - - for (node = set->root; node != NULL; ) - { - int cmp = (compar != NULL - ? compar (node->value, elt) - : (node->value > elt ? 1 : - node->value < elt ? -1 : 0)); - - if (cmp < 0) - node = node->right; - else if (cmp > 0) - node = node->left; - else /* cmp == 0 */ - /* We have an element equal to ELT. */ - return true; - } - return false; -} - -static bool -gl_tree_search_atleast (gl_oset_t set, - gl_setelement_threshold_fn threshold_fn, - const void *threshold, - const void **eltp) -{ - gl_oset_node_t node; - - for (node = set->root; node != NULL; ) - { - if (! threshold_fn (node->value, threshold)) - node = node->right; - else - { - /* We have an element >= VALUE. But we need the leftmost such - element. */ - gl_oset_node_t found = node; - node = node->left; - for (; node != NULL; ) - { - if (! threshold_fn (node->value, threshold)) - node = node->right; - else - { - found = node; - node = node->left; - } - } - *eltp = found->value; - return true; - } - } - return false; -} - -static gl_oset_node_t -gl_tree_search_node (gl_oset_t set, const void *elt) -{ - gl_setelement_compar_fn compar = set->base.compar_fn; - gl_oset_node_t node; - - for (node = set->root; node != NULL; ) - { - int cmp = (compar != NULL - ? compar (node->value, elt) - : (node->value > elt ? 1 : - node->value < elt ? -1 : 0)); - - if (cmp < 0) - node = node->right; - else if (cmp > 0) - node = node->left; - else /* cmp == 0 */ - /* We have an element equal to ELT. */ - return node; - } - return NULL; -} - -static bool -gl_tree_add (gl_oset_t set, const void *elt) -{ - gl_setelement_compar_fn compar; - gl_oset_node_t node = set->root; - - if (node == NULL) - { - gl_tree_add_first (set, elt); - return true; - } - - compar = set->base.compar_fn; - - for (;;) - { - int cmp = (compar != NULL - ? compar (node->value, elt) - : (node->value > elt ? 1 : - node->value < elt ? -1 : 0)); - - if (cmp < 0) - { - if (node->right == NULL) - { - gl_tree_add_after (set, node, elt); - return true; - } - node = node->right; - } - else if (cmp > 0) - { - if (node->left == NULL) - { - gl_tree_add_before (set, node, elt); - return true; - } - node = node->left; - } - else /* cmp == 0 */ - return false; - } -} - -static bool -gl_tree_remove (gl_oset_t set, const void *elt) -{ - gl_oset_node_t node = gl_tree_search_node (set, elt); - - if (node != NULL) - return gl_tree_remove_node (set, node); - else - return false; -} - -static void -gl_tree_oset_free (gl_oset_t set) -{ - /* Iterate across all elements in post-order. */ - gl_oset_node_t node = set->root; - iterstack_t stack; - iterstack_item_t *stack_ptr = &stack[0]; - - for (;;) - { - /* Descend on left branch. */ - for (;;) - { - if (node == NULL) - break; - stack_ptr->node = node; - stack_ptr->rightp = false; - node = node->left; - stack_ptr++; - } - /* Climb up again. */ - for (;;) - { - if (stack_ptr == &stack[0]) - goto done_iterate; - stack_ptr--; - node = stack_ptr->node; - if (!stack_ptr->rightp) - break; - /* Free the current node. */ - free (node); - } - /* Descend on right branch. */ - stack_ptr->rightp = true; - node = node->right; - stack_ptr++; - } - done_iterate: - free (set); -} - -/* --------------------- gl_oset_iterator_t Data Type --------------------- */ - -static gl_oset_iterator_t -gl_tree_iterator (gl_oset_t set) -{ - gl_oset_iterator_t result; - gl_oset_node_t node; - - result.vtable = set->base.vtable; - result.set = set; - /* Start node is the leftmost node. */ - node = set->root; - if (node != NULL) - while (node->left != NULL) - node = node->left; - result.p = node; - /* End point is past the rightmost node. */ - result.q = NULL; -#ifdef lint - result.i = 0; - result.j = 0; - result.count = 0; -#endif - - return result; -} - -static bool -gl_tree_iterator_next (gl_oset_iterator_t *iterator, const void **eltp) -{ - if (iterator->p != iterator->q) - { - gl_oset_node_t node = (gl_oset_node_t) iterator->p; - *eltp = node->value; - /* Advance to the next node. */ - if (node->right != NULL) - { - node = node->right; - while (node->left != NULL) - node = node->left; - } - else - { - while (node->parent != NULL && node->parent->right == node) - node = node->parent; - node = node->parent; - } - iterator->p = node; - return true; - } - else - return false; -} - -static void -gl_tree_iterator_free (gl_oset_iterator_t *iterator) -{ -} diff --git a/src/bin/m4/lib/gl_avltree_oset.c b/src/bin/m4/lib/gl_avltree_oset.c deleted file mode 100644 index 1e38b984f3..0000000000 --- a/src/bin/m4/lib/gl_avltree_oset.c +++ /dev/null @@ -1,572 +0,0 @@ -/* Ordered set data type implemented by a binary tree. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "gl_avltree_oset.h" - -#include - -#include "xalloc.h" - -/* An AVL tree is a binary tree where - 1. The height of each node is calculated as - heightof(node) = 1 + max (heightof(node.left), heightof(node.right)). - 2. The heights of the subtrees of each node differ by at most 1: - | heightof(right) - heightof(left) | <= 1. - 3. The index of the elements in the node.left subtree are smaller than - the index of node. - The index of the elements in the node.right subtree are larger than - the index of node. - */ - -/* -------------------------- gl_oset_t Data Type -------------------------- */ - -/* Tree node implementation, valid for this file only. */ -struct gl_oset_node_impl -{ - struct gl_oset_node_impl *left; /* left branch, or NULL */ - struct gl_oset_node_impl *right; /* right branch, or NULL */ - /* Parent pointer, or NULL. The parent pointer is not needed for most - operations. It is needed so that a gl_oset_node_t can be returned - without memory allocation, on which the functions gl_oset_remove_node, - gl_oset_add_before, gl_oset_add_after can be implemented. */ - struct gl_oset_node_impl *parent; - int balance; /* heightof(right) - heightof(left), - always = -1 or 0 or 1 */ - const void *value; -}; -typedef struct gl_oset_node_impl * gl_oset_node_t; - -/* Concrete gl_oset_impl type, valid for this file only. */ -struct gl_oset_impl -{ - struct gl_oset_impl_base base; - struct gl_oset_node_impl *root; /* root node or NULL */ - size_t count; /* number of nodes */ -}; - -/* An AVL tree of height h has at least F_(h+2) [Fibonacci number] and at most - 2^h - 1 elements. So, h <= 84 (because a tree of height h >= 85 would have - at least F_87 elements, and because even on 64-bit machines, - sizeof (gl_oset_node_impl) * F_87 > 2^64 - this would exceed the address space of the machine. */ -#define MAXHEIGHT 83 - -/* Ensure the tree is balanced, after an insertion or deletion operation. - The height of NODE is incremented by HEIGHT_DIFF (1 or -1). - PARENT = NODE->parent. (NODE can also be NULL. But PARENT is non-NULL.) - Rotation operations are performed starting at PARENT (not NODE itself!). */ -static void -rebalance (gl_oset_t set, - gl_oset_node_t node, int height_diff, gl_oset_node_t parent) -{ - for (;;) - { - gl_oset_node_t child; - int previous_balance; - int balance_diff; - gl_oset_node_t nodeleft; - gl_oset_node_t noderight; - - child = node; - node = parent; - - previous_balance = node->balance; - - /* The balance of NODE is incremented by BALANCE_DIFF: +1 if the right - branch's height has increased by 1 or the left branch's height has - decreased by 1, -1 if the right branch's height has decreased by 1 or - the left branch's height has increased by 1, 0 if no height change. */ - if (node->left != NULL || node->right != NULL) - balance_diff = (child == node->right ? height_diff : -height_diff); - else - /* Special case where above formula doesn't work, because the caller - didn't tell whether node's left or right branch shrunk from height 1 - to NULL. */ - balance_diff = - previous_balance; - - node->balance += balance_diff; - if (balance_diff == previous_balance) - { - /* node->balance is outside the range [-1,1]. Must rotate. */ - gl_oset_node_t *nodep; - - if (node->parent == NULL) - /* node == set->root */ - nodep = &set->root; - else if (node->parent->left == node) - nodep = &node->parent->left; - else if (node->parent->right == node) - nodep = &node->parent->right; - else - abort (); - - nodeleft = node->left; - noderight = node->right; - - if (balance_diff < 0) - { - /* node->balance = -2. The subtree is heavier on the left side. - Rotate from left to right: - - * - / \ - h+2 h - */ - gl_oset_node_t nodeleftright = nodeleft->right; - if (nodeleft->balance <= 0) - { - /* - * h+2|h+3 - / \ / \ - h+2 h --> / h+1|h+2 - / \ | / \ - h+1 h|h+1 h+1 h|h+1 h - */ - node->left = nodeleftright; - nodeleft->right = node; - - nodeleft->parent = node->parent; - node->parent = nodeleft; - if (nodeleftright != NULL) - nodeleftright->parent = node; - - nodeleft->balance += 1; - node->balance = - nodeleft->balance; - - *nodep = nodeleft; - height_diff = (height_diff < 0 - ? /* noderight's height had been decremented from - h+1 to h. The subtree's height changes from - h+3 to h+2|h+3. */ - nodeleft->balance - 1 - : /* nodeleft's height had been incremented from - h+1 to h+2. The subtree's height changes from - h+2 to h+2|h+3. */ - nodeleft->balance); - } - else - { - /* - * h+2 - / \ / \ - h+2 h --> h+1 h+1 - / \ / \ / \ - h h+1 h L R h - / \ - L R - - */ - gl_oset_node_t L = nodeleft->right = nodeleftright->left; - gl_oset_node_t R = node->left = nodeleftright->right; - nodeleftright->left = nodeleft; - nodeleftright->right = node; - - nodeleftright->parent = node->parent; - if (L != NULL) - L->parent = nodeleft; - if (R != NULL) - R->parent = node; - nodeleft->parent = nodeleftright; - node->parent = nodeleftright; - - nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0); - node->balance = (nodeleftright->balance < 0 ? 1 : 0); - nodeleftright->balance = 0; - - *nodep = nodeleftright; - height_diff = (height_diff < 0 - ? /* noderight's height had been decremented from - h+1 to h. The subtree's height changes from - h+3 to h+2. */ - -1 - : /* nodeleft's height had been incremented from - h+1 to h+2. The subtree's height changes from - h+2 to h+2. */ - 0); - } - } - else - { - /* node->balance = 2. The subtree is heavier on the right side. - Rotate from right to left: - - * - / \ - h h+2 - */ - gl_oset_node_t noderightleft = noderight->left; - if (noderight->balance >= 0) - { - /* - * h+2|h+3 - / \ / \ - h h+2 --> h+1|h+2 \ - / \ / \ | - h|h+1 h+1 h h|h+1 h+1 - */ - node->right = noderightleft; - noderight->left = node; - - noderight->parent = node->parent; - node->parent = noderight; - if (noderightleft != NULL) - noderightleft->parent = node; - - noderight->balance -= 1; - node->balance = - noderight->balance; - - *nodep = noderight; - height_diff = (height_diff < 0 - ? /* nodeleft's height had been decremented from - h+1 to h. The subtree's height changes from - h+3 to h+2|h+3. */ - - noderight->balance - 1 - : /* noderight's height had been incremented from - h+1 to h+2. The subtree's height changes from - h+2 to h+2|h+3. */ - - noderight->balance); - } - else - { - /* - * h+2 - / \ / \ - h h+2 --> h+1 h+1 - / \ / \ / \ - h+1 h h L R h - / \ - L R - - */ - gl_oset_node_t L = node->right = noderightleft->left; - gl_oset_node_t R = noderight->left = noderightleft->right; - noderightleft->left = node; - noderightleft->right = noderight; - - noderightleft->parent = node->parent; - if (L != NULL) - L->parent = node; - if (R != NULL) - R->parent = noderight; - node->parent = noderightleft; - noderight->parent = noderightleft; - - node->balance = (noderightleft->balance > 0 ? -1 : 0); - noderight->balance = (noderightleft->balance < 0 ? 1 : 0); - noderightleft->balance = 0; - - *nodep = noderightleft; - height_diff = (height_diff < 0 - ? /* nodeleft's height had been decremented from - h+1 to h. The subtree's height changes from - h+3 to h+2. */ - -1 - : /* noderight's height had been incremented from - h+1 to h+2. The subtree's height changes from - h+2 to h+2. */ - 0); - } - } - node = *nodep; - } - else - { - /* No rotation needed. Only propagation of the height change to the - next higher level. */ - if (height_diff < 0) - height_diff = (previous_balance == 0 ? 0 : -1); - else - height_diff = (node->balance == 0 ? 0 : 1); - } - - if (height_diff == 0) - break; - - parent = node->parent; - if (parent == NULL) - break; - } -} - -static gl_oset_node_t -gl_tree_add_first (gl_oset_t set, const void *elt) -{ - /* Create new node. */ - gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl); - - new_node->left = NULL; - new_node->right = NULL; - new_node->balance = 0; - new_node->value = elt; - - /* Add it to the tree. */ - if (set->root == NULL) - { - set->root = new_node; - new_node->parent = NULL; - } - else - { - gl_oset_node_t node; - - for (node = set->root; node->left != NULL; ) - node = node->left; - - node->left = new_node; - new_node->parent = node; - node->balance--; - - /* Rebalance. */ - if (node->right == NULL && node->parent != NULL) - rebalance (set, node, 1, node->parent); - } - - set->count++; - return new_node; -} - -static gl_oset_node_t -gl_tree_add_before (gl_oset_t set, gl_oset_node_t node, const void *elt) -{ - /* Create new node. */ - gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl); - bool height_inc; - - new_node->left = NULL; - new_node->right = NULL; - new_node->balance = 0; - new_node->value = elt; - - /* Add it to the tree. */ - if (node->left == NULL) - { - node->left = new_node; - node->balance--; - height_inc = (node->right == NULL); - } - else - { - for (node = node->left; node->right != NULL; ) - node = node->right; - node->right = new_node; - node->balance++; - height_inc = (node->left == NULL); - } - new_node->parent = node; - - /* Rebalance. */ - if (height_inc && node->parent != NULL) - rebalance (set, node, 1, node->parent); - - set->count++; - return new_node; -} - -static gl_oset_node_t -gl_tree_add_after (gl_oset_t set, gl_oset_node_t node, const void *elt) -{ - /* Create new node. */ - gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl); - bool height_inc; - - new_node->left = NULL; - new_node->right = NULL; - new_node->balance = 0; - new_node->value = elt; - - /* Add it to the tree. */ - if (node->right == NULL) - { - node->right = new_node; - node->balance++; - height_inc = (node->left == NULL); - } - else - { - for (node = node->right; node->left != NULL; ) - node = node->left; - node->left = new_node; - node->balance--; - height_inc = (node->right == NULL); - } - new_node->parent = node; - - /* Rebalance. */ - if (height_inc && node->parent != NULL) - rebalance (set, node, 1, node->parent); - - set->count++; - return new_node; -} - -static bool -gl_tree_remove_node (gl_oset_t set, gl_oset_node_t node) -{ - gl_oset_node_t parent = node->parent; - - if (node->left == NULL) - { - /* Replace node with node->right. */ - gl_oset_node_t child = node->right; - - if (child != NULL) - child->parent = parent; - if (parent == NULL) - set->root = child; - else - { - if (parent->left == node) - parent->left = child; - else /* parent->right == node */ - parent->right = child; - - rebalance (set, child, -1, parent); - } - } - else if (node->right == NULL) - { - /* It is not absolutely necessary to treat this case. But the more - general case below is more complicated, hence slower. */ - /* Replace node with node->left. */ - gl_oset_node_t child = node->left; - - child->parent = parent; - if (parent == NULL) - set->root = child; - else - { - if (parent->left == node) - parent->left = child; - else /* parent->right == node */ - parent->right = child; - - rebalance (set, child, -1, parent); - } - } - else - { - /* Replace node with the rightmost element of the node->left subtree. */ - gl_oset_node_t subst; - gl_oset_node_t subst_parent; - gl_oset_node_t child; - - for (subst = node->left; subst->right != NULL; ) - subst = subst->right; - - subst_parent = subst->parent; - - child = subst->left; - - /* The case subst_parent == node is special: If we do nothing special, - we get confusion about node->left, subst->left and child->parent. - subst_parent == node - <==> The 'for' loop above terminated immediately. - <==> subst == subst_parent->left - [otherwise subst == subst_parent->right] - In this case, we would need to first set - child->parent = node; node->left = child; - and later - when we copy subst into node's position - again - child->parent = subst; subst->left = child; - Altogether a no-op. */ - if (subst_parent != node) - { - if (child != NULL) - child->parent = subst_parent; - subst_parent->right = child; - } - - /* Copy subst into node's position. - (This is safer than to copy subst's value into node, keep node in - place, and free subst.) */ - if (subst_parent != node) - { - subst->left = node->left; - subst->left->parent = subst; - } - subst->right = node->right; - subst->right->parent = subst; - subst->balance = node->balance; - subst->parent = parent; - if (parent == NULL) - set->root = subst; - else if (parent->left == node) - parent->left = subst; - else /* parent->right == node */ - parent->right = subst; - - /* Rebalancing starts at child's parent, that is subst_parent - - except when subst_parent == node. In this case, we need to use - its replacement, subst. */ - rebalance (set, child, -1, subst_parent != node ? subst_parent : subst); - } - - set->count--; - free (node); - return true; -} - -/* Generic binary tree code. */ -#include "gl_anytree_oset.h" - -/* For debugging. */ -static unsigned int -check_invariants (gl_oset_node_t node, gl_oset_node_t parent, size_t *counterp) -{ - unsigned int left_height = - (node->left != NULL ? check_invariants (node->left, node, counterp) : 0); - unsigned int right_height = - (node->right != NULL ? check_invariants (node->right, node, counterp) : 0); - int balance = (int)right_height - (int)left_height; - - if (!(node->parent == parent)) - abort (); - if (!(balance >= -1 && balance <= 1)) - abort (); - if (!(node->balance == balance)) - abort (); - - (*counterp)++; - - return 1 + (left_height > right_height ? left_height : right_height); -} -void -gl_avltree_oset_check_invariants (gl_oset_t set) -{ - size_t counter = 0; - if (set->root != NULL) - check_invariants (set->root, NULL, &counter); - if (!(set->count == counter)) - abort (); -} - -const struct gl_oset_implementation gl_avltree_oset_implementation = - { - gl_tree_create_empty, - gl_tree_size, - gl_tree_search, - gl_tree_search_atleast, - gl_tree_add, - gl_tree_remove, - gl_tree_oset_free, - gl_tree_iterator, - gl_tree_iterator_next, - gl_tree_iterator_free - }; diff --git a/src/bin/m4/lib/gl_avltree_oset.h b/src/bin/m4/lib/gl_avltree_oset.h deleted file mode 100644 index 27f75d22d0..0000000000 --- a/src/bin/m4/lib/gl_avltree_oset.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Ordered set data type implemented by a binary tree. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_AVLTREE_OSET_H -#define _GL_AVLTREE_OSET_H - -#include "gl_oset.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const struct gl_oset_implementation gl_avltree_oset_implementation; -#define GL_AVLTREE_OSET &gl_avltree_oset_implementation - -#ifdef __cplusplus -} -#endif - -#endif /* _GL_AVLTREE_OSET_H */ diff --git a/src/bin/m4/lib/gl_linkedhash_list.c b/src/bin/m4/lib/gl_linkedhash_list.c deleted file mode 100644 index 89173f51bc..0000000000 --- a/src/bin/m4/lib/gl_linkedhash_list.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Sequential list data type implemented by a hash table with a linked list. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "gl_linkedhash_list.h" - -#include /* for SIZE_MAX */ -#include - -#include "xalloc.h" -#include "xsize.h" - -#ifndef uintptr_t -# define uintptr_t unsigned long -#endif - -#define WITH_HASHTABLE 1 - -/* -------------------------- gl_list_t Data Type -------------------------- */ - -/* Generic hash-table code. */ -#include "gl_anyhash_list1.h" - -/* Generic linked list code. */ -#include "gl_anylinked_list1.h" - -/* Generic hash-table code. */ -#include "gl_anyhash_list2.h" - -/* Resize the hash table if needed, after list->count was incremented. */ -static inline void -hash_resize_after_add (gl_list_t list) -{ - size_t count = list->count; - size_t estimate = xsum (count, count / 2); /* 1.5 * count */ - if (estimate > list->table_size) - hash_resize (list, estimate); -} - -/* Add a node to the hash table structure. */ -static inline void -add_to_bucket (gl_list_t list, gl_list_node_t node) -{ - size_t bucket = node->h.hashcode % list->table_size; - - node->h.hash_next = list->table[bucket]; - list->table[bucket] = &node->h; -} - -/* Remove a node from the hash table structure. */ -static inline void -remove_from_bucket (gl_list_t list, gl_list_node_t node) -{ - size_t bucket = node->h.hashcode % list->table_size; - gl_hash_entry_t *p; - - for (p = &list->table[bucket]; ; p = &(*p)->hash_next) - { - if (*p == &node->h) - { - *p = node->h.hash_next; - break; - } - if (*p == NULL) - /* node is not in the right bucket. Did the hash codes - change inadvertently? */ - abort (); - } -} - -/* Generic linked list code. */ -#include "gl_anylinked_list2.h" - - -const struct gl_list_implementation gl_linkedhash_list_implementation = - { - gl_linked_create_empty, - gl_linked_create, - gl_linked_size, - gl_linked_node_value, - gl_linked_next_node, - gl_linked_previous_node, - gl_linked_get_at, - gl_linked_set_at, - gl_linked_search_from_to, - gl_linked_indexof_from_to, - gl_linked_add_first, - gl_linked_add_last, - gl_linked_add_before, - gl_linked_add_after, - gl_linked_add_at, - gl_linked_remove_node, - gl_linked_remove_at, - gl_linked_remove, - gl_linked_list_free, - gl_linked_iterator, - gl_linked_iterator_from_to, - gl_linked_iterator_next, - gl_linked_iterator_free, - gl_linked_sortedlist_search, - gl_linked_sortedlist_search_from_to, - gl_linked_sortedlist_indexof, - gl_linked_sortedlist_indexof_from_to, - gl_linked_sortedlist_add, - gl_linked_sortedlist_remove - }; diff --git a/src/bin/m4/lib/gl_linkedhash_list.h b/src/bin/m4/lib/gl_linkedhash_list.h deleted file mode 100644 index d3e71ed95d..0000000000 --- a/src/bin/m4/lib/gl_linkedhash_list.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Sequential list data type implemented by a hash table with a linked list. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_LINKEDHASH_LIST_H -#define _GL_LINKEDHASH_LIST_H - -#include "gl_list.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const struct gl_list_implementation gl_linkedhash_list_implementation; -#define GL_LINKEDHASH_LIST &gl_linkedhash_list_implementation - -#ifdef __cplusplus -} -#endif - -#endif /* _GL_LINKEDHASH_LIST_H */ diff --git a/src/bin/m4/lib/gl_list.c b/src/bin/m4/lib/gl_list.c deleted file mode 100644 index cbc765a944..0000000000 --- a/src/bin/m4/lib/gl_list.c +++ /dev/null @@ -1,272 +0,0 @@ -/* Abstract sequential list data type. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "gl_list.h" - -#if !HAVE_INLINE - -/* Define all functions of this file as inline accesses to the - struct gl_list_implementation. - Use #define to avoid a warning because of extern vs. static. */ - -gl_list_t -gl_list_create_empty (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates) -{ - return implementation->create_empty (implementation, equals_fn, hashcode_fn, - allow_duplicates); -} - -gl_list_t -gl_list_create (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates, - size_t count, const void **contents) -{ - return implementation->create (implementation, equals_fn, hashcode_fn, - allow_duplicates, count, contents); -} - -size_t -gl_list_size (gl_list_t list) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->size (list); -} - -const void * -gl_list_node_value (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->node_value (list, node); -} - -gl_list_node_t -gl_list_next_node (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->next_node (list, node); -} - -gl_list_node_t -gl_list_previous_node (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->previous_node (list, node); -} - -const void * -gl_list_get_at (gl_list_t list, size_t position) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->get_at (list, position); -} - -gl_list_node_t -gl_list_set_at (gl_list_t list, size_t position, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->set_at (list, position, elt); -} - -gl_list_node_t -gl_list_search (gl_list_t list, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->search_from_to (list, 0, size, elt); -} - -gl_list_node_t -gl_list_search_from (gl_list_t list, size_t start_index, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->search_from_to (list, start_index, size, elt); -} - -gl_list_node_t -gl_list_search_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->search_from_to (list, start_index, end_index, elt); -} - -size_t -gl_list_indexof (gl_list_t list, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->indexof_from_to (list, 0, size, elt); -} - -size_t -gl_list_indexof_from (gl_list_t list, size_t start_index, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->indexof_from_to (list, start_index, size, elt); -} - -size_t -gl_list_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->indexof_from_to (list, start_index, end_index, elt); -} - -gl_list_node_t -gl_list_add_first (gl_list_t list, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_first (list, elt); -} - -gl_list_node_t -gl_list_add_last (gl_list_t list, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_last (list, elt); -} - -gl_list_node_t -gl_list_add_before (gl_list_t list, gl_list_node_t node, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_before (list, node, elt); -} - -gl_list_node_t -gl_list_add_after (gl_list_t list, gl_list_node_t node, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_after (list, node, elt); -} - -gl_list_node_t -gl_list_add_at (gl_list_t list, size_t position, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_at (list, position, elt); -} - -bool -gl_list_remove_node (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->remove_node (list, node); -} - -bool -gl_list_remove_at (gl_list_t list, size_t position) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->remove_at (list, position); -} - -bool -gl_list_remove (gl_list_t list, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->remove (list, elt); -} - -void -gl_list_free (gl_list_t list) -{ - ((const struct gl_list_impl_base *) list)->vtable->list_free (list); -} - -gl_list_iterator_t -gl_list_iterator (gl_list_t list) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->iterator (list); -} - -gl_list_iterator_t -gl_list_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->iterator_from_to (list, start_index, end_index); -} - -bool -gl_list_iterator_next (gl_list_iterator_t *iterator, - const void **eltp, gl_list_node_t *nodep) -{ - return iterator->vtable->iterator_next (iterator, eltp, nodep); -} - -void -gl_list_iterator_free (gl_list_iterator_t *iterator) -{ - iterator->vtable->iterator_free (iterator); -} - -gl_list_node_t -gl_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_search (list, compar, elt); -} - -gl_list_node_t -gl_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_search_from_to (list, compar, start_index, end_index, - elt); -} - -size_t -gl_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_indexof (list, compar, elt); -} - -size_t -gl_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_indexof_from_to (list, compar, start_index, end_index, - elt); -} - -gl_list_node_t -gl_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_add (list, compar, elt); -} - -bool -gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_remove (list, compar, elt); -} - -#endif diff --git a/src/bin/m4/lib/gl_list.h b/src/bin/m4/lib/gl_list.h deleted file mode 100644 index b97a6a42a3..0000000000 --- a/src/bin/m4/lib/gl_list.h +++ /dev/null @@ -1,724 +0,0 @@ -/* Abstract sequential list data type. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_LIST_H -#define _GL_LIST_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* gl_list is an abstract list data type. It can contain any number of - objects ('void *' or 'const void *' pointers) in any given order. - Duplicates are allowed, but can optionally be forbidden. - - There are several implementations of this list datatype, optimized for - different operations or for memory. You can start using the simplest list - implementation, GL_ARRAY_LIST, and switch to a different implementation - later, when you realize which operations are performed the most frequently. - The API of the different implementations is exactly the same; when - switching to a different implementation, you only have to change the - gl_list_create call. - - The implementations are: - GL_ARRAY_LIST a growable array - GL_CARRAY_LIST a growable circular array - GL_LINKED_LIST a linked list - GL_AVLTREE_LIST a binary tree (AVL tree) - GL_RBTREE_LIST a binary tree (red-black tree) - GL_LINKEDHASH_LIST a hash table with a linked list - GL_AVLTREEHASH_LIST a hash table with a binary tree (AVL tree) - GL_RBTREEHASH_LIST a hash table with a binary tree (red-black tree) - - The memory consumption is asymptotically the same: O(1) for every object - in the list. When looking more closely at the average memory consumed - for an object, GL_ARRAY_LIST is the most compact representation, and - GL_LINKEDHASH_LIST and GL_TREEHASH_LIST need more memory. - - The guaranteed average performance of the operations is, for a list of - n elements: - - Operation ARRAY LINKED TREE LINKEDHASH TREEHASH - CARRAY with|without with|without - duplicates duplicates - - gl_list_size O(1) O(1) O(1) O(1) O(1) - gl_list_node_value O(1) O(1) O(1) O(1) O(1) - gl_list_next_node O(1) O(1) O(log n) O(1) O(log n) - gl_list_previous_node O(1) O(1) O(log n) O(1) O(log n) - gl_list_get_at O(1) O(n) O(log n) O(n) O(log n) - gl_list_set_at O(1) O(n) O(log n) O(n) O((log n)²)/O(log n) - gl_list_search O(n) O(n) O(n) O(n)/O(1) O(log n)/O(1) - gl_list_search_from O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) - gl_list_search_from_to O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) - gl_list_indexof O(n) O(n) O(n) O(n) O(log n) - gl_list_indexof_from O(n) O(n) O(n) O(n) O((log n)²)/O(log n) - gl_list_indexof_from_to O(n) O(n) O(n) O(n) O((log n)²)/O(log n) - gl_list_add_first O(n)/O(1) O(1) O(log n) O(1) O((log n)²)/O(log n) - gl_list_add_last O(1) O(1) O(log n) O(1) O((log n)²)/O(log n) - gl_list_add_before O(n) O(1) O(log n) O(1) O((log n)²)/O(log n) - gl_list_add_after O(n) O(1) O(log n) O(1) O((log n)²)/O(log n) - gl_list_add_at O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) - gl_list_remove_node O(n) O(1) O(log n) O(n)/O(1) O((log n)²)/O(log n) - gl_list_remove_at O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) - gl_list_remove O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) - gl_list_iterator O(1) O(1) O(log n) O(1) O(log n) - gl_list_iterator_from_to O(1) O(n) O(log n) O(n) O(log n) - gl_list_iterator_next O(1) O(1) O(log n) O(1) O(log n) - gl_sortedlist_search O(log n) O(n) O(log n) O(n) O(log n) - gl_sortedlist_search_from O(log n) O(n) O(log n) O(n) O(log n) - gl_sortedlist_indexof O(log n) O(n) O(log n) O(n) O(log n) - gl_sortedlist_indexof_fro O(log n) O(n) O(log n) O(n) O(log n) - gl_sortedlist_add O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) - gl_sortedlist_remove O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) - */ - -/* -------------------------- gl_list_t Data Type -------------------------- */ - -/* Type of function used to compare two elements. - NULL denotes pointer comparison. */ -typedef bool (*gl_listelement_equals_fn) (const void *elt1, const void *elt2); - -/* Type of function used to compute a hash code. - NULL denotes a function that depends only on the pointer itself. */ -typedef size_t (*gl_listelement_hashcode_fn) (const void *elt); - -struct gl_list_impl; -/* Type representing an entire list. */ -typedef struct gl_list_impl * gl_list_t; - -struct gl_list_node_impl; -/* Type representing the position of an element in the list, in a way that - is more adapted to the list implementation than a plain index. - Note: It is invalidated by insertions and removals! */ -typedef struct gl_list_node_impl * gl_list_node_t; - -struct gl_list_implementation; -/* Type representing a list datatype implementation. */ -typedef const struct gl_list_implementation * gl_list_implementation_t; - -/* Create an empty list. - IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST, - GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST, - GL_RBTREEHASH_LIST. - EQUALS_FN is an element comparison function or NULL. - HASHCODE_FN is an element hash code function or NULL. - ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in - the list. The implementation may verify this at runtime. */ -extern gl_list_t gl_list_create_empty (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates); - -/* Create a list with given contents. - IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST, - GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST, - GL_RBTREEHASH_LIST. - EQUALS_FN is an element comparison function or NULL. - HASHCODE_FN is an element hash code function or NULL. - ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in - the list. The implementation may verify this at runtime. - COUNT is the number of initial elements. - CONTENTS[0..COUNT-1] is the initial contents. */ -extern gl_list_t gl_list_create (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates, - size_t count, const void **contents); - -/* Return the current number of elements in a list. */ -extern size_t gl_list_size (gl_list_t list); - -/* Return the element value represented by a list node. */ -extern const void * gl_list_node_value (gl_list_t list, gl_list_node_t node); - -/* Return the node immediately after the given node in the list, or NULL - if the given node is the last (rightmost) one in the list. */ -extern gl_list_node_t gl_list_next_node (gl_list_t list, gl_list_node_t node); - -/* Return the node immediately before the given node in the list, or NULL - if the given node is the first (leftmost) one in the list. */ -extern gl_list_node_t gl_list_previous_node (gl_list_t list, gl_list_node_t node); - -/* Return the element at a given position in the list. - POSITION must be >= 0 and < gl_list_size (list). */ -extern const void * gl_list_get_at (gl_list_t list, size_t position); - -/* Replace the element at a given position in the list. - POSITION must be >= 0 and < gl_list_size (list). - Return its node. */ -extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position, - const void *elt); - -/* Search whether an element is already in the list. - Return its node if found, or NULL if not present in the list. */ -extern gl_list_node_t gl_list_search (gl_list_t list, const void *elt); - -/* Search whether an element is already in the list, - at a position >= START_INDEX. - Return its node if found, or NULL if not present in the list. */ -extern gl_list_node_t gl_list_search_from (gl_list_t list, size_t start_index, - const void *elt); - -/* Search whether an element is already in the list, - at a position >= START_INDEX and < END_INDEX. - Return its node if found, or NULL if not present in the list. */ -extern gl_list_node_t gl_list_search_from_to (gl_list_t list, - size_t start_index, - size_t end_index, - const void *elt); - -/* Search whether an element is already in the list. - Return its position if found, or (size_t)(-1) if not present in the list. */ -extern size_t gl_list_indexof (gl_list_t list, const void *elt); - -/* Search whether an element is already in the list, - at a position >= START_INDEX. - Return its position if found, or (size_t)(-1) if not present in the list. */ -extern size_t gl_list_indexof_from (gl_list_t list, size_t start_index, - const void *elt); - -/* Search whether an element is already in the list, - at a position >= START_INDEX and < END_INDEX. - Return its position if found, or (size_t)(-1) if not present in the list. */ -extern size_t gl_list_indexof_from_to (gl_list_t list, - size_t start_index, size_t end_index, - const void *elt); - -/* Add an element as the first element of the list. - Return its node. */ -extern gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt); - -/* Add an element as the last element of the list. - Return its node. */ -extern gl_list_node_t gl_list_add_last (gl_list_t list, const void *elt); - -/* Add an element before a given element node of the list. - Return its node. */ -extern gl_list_node_t gl_list_add_before (gl_list_t list, gl_list_node_t node, - const void *elt); - -/* Add an element after a given element node of the list. - Return its node. */ -extern gl_list_node_t gl_list_add_after (gl_list_t list, gl_list_node_t node, - const void *elt); - -/* Add an element add a given position in the list. - POSITION must be >= 0 and <= gl_list_size (list). */ -extern gl_list_node_t gl_list_add_at (gl_list_t list, size_t position, - const void *elt); - -/* Remove an element from the list. - Return true. */ -extern bool gl_list_remove_node (gl_list_t list, gl_list_node_t node); - -/* Remove an element at a given position from the list. - POSITION must be >= 0 and < gl_list_size (list). - Return true. */ -extern bool gl_list_remove_at (gl_list_t list, size_t position); - -/* Search and remove an element from the list. - Return true if it was found and removed. */ -extern bool gl_list_remove (gl_list_t list, const void *elt); - -/* Free an entire list. - (But this call does not free the elements of the list.) */ -extern void gl_list_free (gl_list_t list); - -/* --------------------- gl_list_iterator_t Data Type --------------------- */ - -/* Functions for iterating through a list. */ - -/* Type of an iterator that traverses a list. - This is a fixed-size struct, so that creation of an iterator doesn't need - memory allocation on the heap. */ -typedef struct -{ - /* For fast dispatch of gl_list_iterator_next. */ - const struct gl_list_implementation *vtable; - /* For detecting whether the last returned element was removed. */ - gl_list_t list; - size_t count; - /* Other, implementation-private fields. */ - void *p; void *q; - size_t i; size_t j; -} gl_list_iterator_t; - -/* Create an iterator traversing a list. - The list contents must not be modified while the iterator is in use, - except for replacing or removing the last returned element. */ -extern gl_list_iterator_t gl_list_iterator (gl_list_t list); - -/* Create an iterator traversing the element with indices i, - start_index <= i < end_index, of a list. - The list contents must not be modified while the iterator is in use, - except for replacing or removing the last returned element. */ -extern gl_list_iterator_t gl_list_iterator_from_to (gl_list_t list, - size_t start_index, - size_t end_index); - -/* If there is a next element, store the next element in *ELTP, store its - node in *NODEP if NODEP is non-NULL, advance the iterator and return true. - Otherwise, return false. */ -extern bool gl_list_iterator_next (gl_list_iterator_t *iterator, - const void **eltp, gl_list_node_t *nodep); - -/* Free an iterator. */ -extern void gl_list_iterator_free (gl_list_iterator_t *iterator); - -/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ - -/* The following functions are for lists without duplicates where the - order is given by a sort criterion. */ - -/* Type of function used to compare two elements. Same as for qsort(). - NULL denotes pointer comparison. */ -typedef int (*gl_listelement_compar_fn) (const void *elt1, const void *elt2); - -/* Search whether an element is already in the list. - The list is assumed to be sorted with COMPAR. - Return its node if found, or NULL if not present in the list. - If the list contains several copies of ELT, the node of the leftmost one is - returned. */ -extern gl_list_node_t gl_sortedlist_search (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - -/* Search whether an element is already in the list. - The list is assumed to be sorted with COMPAR. - Only list elements with indices >= START_INDEX and < END_INDEX are - considered; the implementation uses these bounds to minimize the number - of COMPAR invocations. - Return its node if found, or NULL if not present in the list. - If the list contains several copies of ELT, the node of the leftmost one is - returned. */ -extern gl_list_node_t gl_sortedlist_search_from_to (gl_list_t list, - gl_listelement_compar_fn compar, - size_t start_index, - size_t end_index, - const void *elt); - -/* Search whether an element is already in the list. - The list is assumed to be sorted with COMPAR. - Return its position if found, or (size_t)(-1) if not present in the list. - If the list contains several copies of ELT, the position of the leftmost one - is returned. */ -extern size_t gl_sortedlist_indexof (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - -/* Search whether an element is already in the list. - The list is assumed to be sorted with COMPAR. - Only list elements with indices >= START_INDEX and < END_INDEX are - considered; the implementation uses these bounds to minimize the number - of COMPAR invocations. - Return its position if found, or (size_t)(-1) if not present in the list. - If the list contains several copies of ELT, the position of the leftmost one - is returned. */ -extern size_t gl_sortedlist_indexof_from_to (gl_list_t list, - gl_listelement_compar_fn compar, - size_t start_index, - size_t end_index, - const void *elt); - -/* Add an element at the appropriate position in the list. - The list is assumed to be sorted with COMPAR. - Return its node. */ -extern gl_list_node_t gl_sortedlist_add (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - -/* Search and remove an element from the list. - The list is assumed to be sorted with COMPAR. - Return true if it was found and removed. - If the list contains several copies of ELT, only the leftmost one is - removed. */ -extern bool gl_sortedlist_remove (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - -/* ------------------------ Implementation Details ------------------------ */ - -struct gl_list_implementation -{ - /* gl_list_t functions. */ - gl_list_t (*create_empty) (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates); - gl_list_t (*create) (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates, - size_t count, const void **contents); - size_t (*size) (gl_list_t list); - const void * (*node_value) (gl_list_t list, gl_list_node_t node); - gl_list_node_t (*next_node) (gl_list_t list, gl_list_node_t node); - gl_list_node_t (*previous_node) (gl_list_t list, gl_list_node_t node); - const void * (*get_at) (gl_list_t list, size_t position); - gl_list_node_t (*set_at) (gl_list_t list, size_t position, const void *elt); - gl_list_node_t (*search_from_to) (gl_list_t list, size_t start_index, - size_t end_index, const void *elt); - size_t (*indexof_from_to) (gl_list_t list, size_t start_index, - size_t end_index, const void *elt); - gl_list_node_t (*add_first) (gl_list_t list, const void *elt); - gl_list_node_t (*add_last) (gl_list_t list, const void *elt); - gl_list_node_t (*add_before) (gl_list_t list, gl_list_node_t node, - const void *elt); - gl_list_node_t (*add_after) (gl_list_t list, gl_list_node_t node, - const void *elt); - gl_list_node_t (*add_at) (gl_list_t list, size_t position, - const void *elt); - bool (*remove_node) (gl_list_t list, gl_list_node_t node); - bool (*remove_at) (gl_list_t list, size_t position); - bool (*remove) (gl_list_t list, const void *elt); - void (*list_free) (gl_list_t list); - /* gl_list_iterator_t functions. */ - gl_list_iterator_t (*iterator) (gl_list_t list); - gl_list_iterator_t (*iterator_from_to) (gl_list_t list, - size_t start_index, - size_t end_index); - bool (*iterator_next) (gl_list_iterator_t *iterator, - const void **eltp, gl_list_node_t *nodep); - void (*iterator_free) (gl_list_iterator_t *iterator); - /* Sorted gl_list_t functions. */ - gl_list_node_t (*sortedlist_search) (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - gl_list_node_t (*sortedlist_search_from_to) (gl_list_t list, - gl_listelement_compar_fn compar, - size_t start_index, - size_t end_index, - const void *elt); - size_t (*sortedlist_indexof) (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - size_t (*sortedlist_indexof_from_to) (gl_list_t list, - gl_listelement_compar_fn compar, - size_t start_index, size_t end_index, - const void *elt); - gl_list_node_t (*sortedlist_add) (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); - bool (*sortedlist_remove) (gl_list_t list, - gl_listelement_compar_fn compar, - const void *elt); -}; - -struct gl_list_impl_base -{ - const struct gl_list_implementation *vtable; - gl_listelement_equals_fn equals_fn; - gl_listelement_hashcode_fn hashcode_fn; - bool allow_duplicates; -}; - -#if HAVE_INLINE - -/* Define all functions of this file as inline accesses to the - struct gl_list_implementation. - Use #define to avoid a warning because of extern vs. static. */ - -# define gl_list_create_empty gl_list_create_empty_inline -static inline gl_list_t -gl_list_create_empty (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates) -{ - return implementation->create_empty (implementation, equals_fn, hashcode_fn, - allow_duplicates); -} - -# define gl_list_create gl_list_create_inline -static inline gl_list_t -gl_list_create (gl_list_implementation_t implementation, - gl_listelement_equals_fn equals_fn, - gl_listelement_hashcode_fn hashcode_fn, - bool allow_duplicates, - size_t count, const void **contents) -{ - return implementation->create (implementation, equals_fn, hashcode_fn, - allow_duplicates, count, contents); -} - -# define gl_list_size gl_list_size_inline -static inline size_t -gl_list_size (gl_list_t list) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->size (list); -} - -# define gl_list_node_value gl_list_node_value_inline -static inline const void * -gl_list_node_value (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->node_value (list, node); -} - -# define gl_list_next_node gl_list_next_node_inline -static inline gl_list_node_t -gl_list_next_node (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->next_node (list, node); -} - -# define gl_list_previous_node gl_list_previous_node_inline -static inline gl_list_node_t -gl_list_previous_node (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->previous_node (list, node); -} - -# define gl_list_get_at gl_list_get_at_inline -static inline const void * -gl_list_get_at (gl_list_t list, size_t position) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->get_at (list, position); -} - -# define gl_list_set_at gl_list_set_at_inline -static inline gl_list_node_t -gl_list_set_at (gl_list_t list, size_t position, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->set_at (list, position, elt); -} - -# define gl_list_search gl_list_search_inline -static inline gl_list_node_t -gl_list_search (gl_list_t list, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->search_from_to (list, 0, size, elt); -} - -# define gl_list_search_from gl_list_search_from_inline -static inline gl_list_node_t -gl_list_search_from (gl_list_t list, size_t start_index, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->search_from_to (list, start_index, size, elt); -} - -# define gl_list_search_from_to gl_list_search_from_to_inline -static inline gl_list_node_t -gl_list_search_from_to (gl_list_t list, size_t start_index, size_t end_index, - const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->search_from_to (list, start_index, end_index, elt); -} - -# define gl_list_indexof gl_list_indexof_inline -static inline size_t -gl_list_indexof (gl_list_t list, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->indexof_from_to (list, 0, size, elt); -} - -# define gl_list_indexof_from gl_list_indexof_from_inline -static inline size_t -gl_list_indexof_from (gl_list_t list, size_t start_index, const void *elt) -{ - size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); - return ((const struct gl_list_impl_base *) list)->vtable - ->indexof_from_to (list, start_index, size, elt); -} - -# define gl_list_indexof_from_to gl_list_indexof_from_to_inline -static inline size_t -gl_list_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, - const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->indexof_from_to (list, start_index, end_index, elt); -} - -# define gl_list_add_first gl_list_add_first_inline -static inline gl_list_node_t -gl_list_add_first (gl_list_t list, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_first (list, elt); -} - -# define gl_list_add_last gl_list_add_last_inline -static inline gl_list_node_t -gl_list_add_last (gl_list_t list, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_last (list, elt); -} - -# define gl_list_add_before gl_list_add_before_inline -static inline gl_list_node_t -gl_list_add_before (gl_list_t list, gl_list_node_t node, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_before (list, node, elt); -} - -# define gl_list_add_after gl_list_add_after_inline -static inline gl_list_node_t -gl_list_add_after (gl_list_t list, gl_list_node_t node, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_after (list, node, elt); -} - -# define gl_list_add_at gl_list_add_at_inline -static inline gl_list_node_t -gl_list_add_at (gl_list_t list, size_t position, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->add_at (list, position, elt); -} - -# define gl_list_remove_node gl_list_remove_node_inline -static inline bool -gl_list_remove_node (gl_list_t list, gl_list_node_t node) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->remove_node (list, node); -} - -# define gl_list_remove_at gl_list_remove_at_inline -static inline bool -gl_list_remove_at (gl_list_t list, size_t position) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->remove_at (list, position); -} - -# define gl_list_remove gl_list_remove_inline -static inline bool -gl_list_remove (gl_list_t list, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->remove (list, elt); -} - -# define gl_list_free gl_list_free_inline -static inline void -gl_list_free (gl_list_t list) -{ - ((const struct gl_list_impl_base *) list)->vtable->list_free (list); -} - -# define gl_list_iterator gl_list_iterator_inline -static inline gl_list_iterator_t -gl_list_iterator (gl_list_t list) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->iterator (list); -} - -# define gl_list_iterator_from_to gl_list_iterator_from_to_inline -static inline gl_list_iterator_t -gl_list_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->iterator_from_to (list, start_index, end_index); -} - -# define gl_list_iterator_next gl_list_iterator_next_inline -static inline bool -gl_list_iterator_next (gl_list_iterator_t *iterator, - const void **eltp, gl_list_node_t *nodep) -{ - return iterator->vtable->iterator_next (iterator, eltp, nodep); -} - -# define gl_list_iterator_free gl_list_iterator_free_inline -static inline void -gl_list_iterator_free (gl_list_iterator_t *iterator) -{ - iterator->vtable->iterator_free (iterator); -} - -# define gl_sortedlist_search gl_sortedlist_search_inline -static inline gl_list_node_t -gl_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_search (list, compar, elt); -} - -# define gl_sortedlist_search_from_to gl_sortedlist_search_from_to_inline -static inline gl_list_node_t -gl_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_search_from_to (list, compar, start_index, end_index, - elt); -} - -# define gl_sortedlist_indexof gl_sortedlist_indexof_inline -static inline size_t -gl_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_indexof (list, compar, elt); -} - -# define gl_sortedlist_indexof_from_to gl_sortedlist_indexof_from_to_inline -static inline size_t -gl_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_indexof_from_to (list, compar, start_index, end_index, - elt); -} - -# define gl_sortedlist_add gl_sortedlist_add_inline -static inline gl_list_node_t -gl_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_add (list, compar, elt); -} - -# define gl_sortedlist_remove gl_sortedlist_remove_inline -static inline bool -gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) -{ - return ((const struct gl_list_impl_base *) list)->vtable - ->sortedlist_remove (list, compar, elt); -} - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _GL_LIST_H */ diff --git a/src/bin/m4/lib/gl_oset.c b/src/bin/m4/lib/gl_oset.c deleted file mode 100644 index 83f964e0ce..0000000000 --- a/src/bin/m4/lib/gl_oset.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Abstract ordered set data type. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "gl_oset.h" - -#if !HAVE_INLINE - -/* Define all functions of this file as inline accesses to the - struct gl_list_implementation. - Use #define to avoid a warning because of extern vs. static. */ - -gl_oset_t -gl_oset_create_empty (gl_oset_implementation_t implementation, - gl_setelement_compar_fn compar_fn) -{ - return implementation->create_empty (implementation, compar_fn); -} - -size_t -gl_oset_size (gl_oset_t set) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->size (set); -} - -bool -gl_oset_search (gl_oset_t set, const void *elt) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt); -} - -bool -gl_oset_search_atleast (gl_oset_t set, - gl_setelement_threshold_fn threshold_fn, - const void *threshold, const void **eltp) -{ - return ((const struct gl_oset_impl_base *) set)->vtable - ->search_atleast (set, threshold_fn, threshold, eltp); -} - -bool -gl_oset_add (gl_oset_t set, const void *elt) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->add (set, elt); -} - -bool -gl_oset_remove (gl_oset_t set, const void *elt) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->remove (set, elt); -} - -void -gl_oset_free (gl_oset_t set) -{ - ((const struct gl_oset_impl_base *) set)->vtable->oset_free (set); -} - -gl_oset_iterator_t -gl_oset_iterator (gl_oset_t set) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set); -} - -bool -gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp) -{ - return iterator->vtable->iterator_next (iterator, eltp); -} - -void -gl_oset_iterator_free (gl_oset_iterator_t *iterator) -{ - iterator->vtable->iterator_free (iterator); -} - -#endif diff --git a/src/bin/m4/lib/gl_oset.h b/src/bin/m4/lib/gl_oset.h deleted file mode 100644 index fb36aac1cf..0000000000 --- a/src/bin/m4/lib/gl_oset.h +++ /dev/null @@ -1,265 +0,0 @@ -/* Abstract ordered set data type. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_OSET_H -#define _GL_OSET_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* gl_oset is an abstract ordered set data type. It can contain any number - of objects ('void *' or 'const void *' pointers) in the order of a given - comparator function. Duplicates (in the sense of the comparator) are - forbidden. - - There are several implementations of this ordered set datatype, optimized - for different operations or for memory. You can start using the simplest - ordered set implementation, GL_ARRAY_OSET, and switch to a different - implementation later, when you realize which operations are performed - the most frequently. The API of the different implementations is exactly - the same; when switching to a different implementation, you only have to - change the gl_oset_create call. - - The implementations are: - GL_ARRAY_OSET a growable array - GL_AVLTREE_OSET a binary tree (AVL tree) - GL_RBTREE_OSET a binary tree (red-black tree) - - The memory consumption is asymptotically the same: O(1) for every object - in the set. When looking more closely at the average memory consumed - for an object, GL_ARRAY_OSET is the most compact representation, and - GL_AVLTREE_OSET, GL_RBTREE_OSET need more memory. - - The guaranteed average performance of the operations is, for a set of - n elements: - - Operation ARRAY TREE - - gl_oset_size O(1) O(1) - gl_oset_add O(n) O(log n) - gl_oset_remove O(n) O(log n) - gl_oset_search O(log n) O(log n) - gl_oset_search_atleast O(log n) O(log n) - gl_oset_iterator O(1) O(log n) - gl_oset_iterator_next O(1) O(log n) - */ - -/* -------------------------- gl_oset_t Data Type -------------------------- */ - -/* Type of function used to compare two elements. Same as for qsort(). - NULL denotes pointer comparison. */ -typedef int (*gl_setelement_compar_fn) (const void *elt1, const void *elt2); - -/* Type of function used to compare an element with a threshold. - Return true if the element is greater or equal than the threshold. */ -typedef bool (*gl_setelement_threshold_fn) (const void *elt, const void *threshold); - -struct gl_oset_impl; -/* Type representing an entire ordered set. */ -typedef struct gl_oset_impl * gl_oset_t; - -struct gl_oset_implementation; -/* Type representing a ordered set datatype implementation. */ -typedef const struct gl_oset_implementation * gl_oset_implementation_t; - -/* Create an empty set. - IMPLEMENTATION is one of GL_ARRAY_OSET, GL_AVLTREE_OSET, GL_RBTREE_OSET. - COMPAR_FN is an element comparison function or NULL. */ -extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation, - gl_setelement_compar_fn compar_fn); - -/* Return the current number of elements in an ordered set. */ -extern size_t gl_oset_size (gl_oset_t set); - -/* Search whether an element is already in the ordered set. - Return true if found, or false if not present in the set. */ -extern bool gl_oset_search (gl_oset_t set, const void *elt); - -/* Search the least element in the ordered set that compares greater or equal - to the given THRESHOLD. The representation of the THRESHOLD is defined - by the THRESHOLD_FN. - Return true and store the found element in *ELTP if found, otherwise return - false. */ -extern bool gl_oset_search_atleast (gl_oset_t set, - gl_setelement_threshold_fn threshold_fn, - const void *threshold, - const void **eltp); - -/* Add an element to an ordered set. - Return true if it was not already in the set and added. */ -extern bool gl_oset_add (gl_oset_t set, const void *elt); - -/* Remove an element from an ordered set. - Return true if it was found and removed. */ -extern bool gl_oset_remove (gl_oset_t set, const void *elt); - -/* Free an entire ordered set. - (But this call does not free the elements of the set.) */ -extern void gl_oset_free (gl_oset_t set); - -/* --------------------- gl_oset_iterator_t Data Type --------------------- */ - -/* Functions for iterating through an ordered set. */ - -/* Type of an iterator that traverses an ordered set. - This is a fixed-size struct, so that creation of an iterator doesn't need - memory allocation on the heap. */ -typedef struct -{ - /* For fast dispatch of gl_oset_iterator_next. */ - const struct gl_oset_implementation *vtable; - /* For detecting whether the last returned element was removed. */ - gl_oset_t set; - size_t count; - /* Other, implementation-private fields. */ - void *p; void *q; - size_t i; size_t j; -} gl_oset_iterator_t; - -/* Create an iterator traversing an ordered set. - The set's contents must not be modified while the iterator is in use, - except for removing the last returned element. */ -extern gl_oset_iterator_t gl_oset_iterator (gl_oset_t set); - -/* If there is a next element, store the next element in *ELTP, advance the - iterator and return true. Otherwise, return false. */ -extern bool gl_oset_iterator_next (gl_oset_iterator_t *iterator, - const void **eltp); - -/* Free an iterator. */ -extern void gl_oset_iterator_free (gl_oset_iterator_t *iterator); - -/* ------------------------ Implementation Details ------------------------ */ - -struct gl_oset_implementation -{ - /* gl_oset_t functions. */ - gl_oset_t (*create_empty) (gl_oset_implementation_t implementation, - gl_setelement_compar_fn compar_fn); - size_t (*size) (gl_oset_t set); - bool (*search) (gl_oset_t set, const void *elt); - bool (*search_atleast) (gl_oset_t set, - gl_setelement_threshold_fn threshold_fn, - const void *threshold, const void **eltp); - bool (*add) (gl_oset_t set, const void *elt); - bool (*remove) (gl_oset_t set, const void *elt); - void (*oset_free) (gl_oset_t set); - /* gl_oset_iterator_t functions. */ - gl_oset_iterator_t (*iterator) (gl_oset_t set); - bool (*iterator_next) (gl_oset_iterator_t *iterator, const void **eltp); - void (*iterator_free) (gl_oset_iterator_t *iterator); -}; - -struct gl_oset_impl_base -{ - const struct gl_oset_implementation *vtable; - gl_setelement_compar_fn compar_fn; -}; - -#if HAVE_INLINE - -/* Define all functions of this file as inline accesses to the - struct gl_oset_implementation. - Use #define to avoid a warning because of extern vs. static. */ - -# define gl_oset_create_empty gl_oset_create_empty_inline -static inline gl_oset_t -gl_oset_create_empty (gl_oset_implementation_t implementation, - gl_setelement_compar_fn compar_fn) -{ - return implementation->create_empty (implementation, compar_fn); -} - -# define gl_oset_size gl_oset_size_inline -static inline size_t -gl_oset_size (gl_oset_t set) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->size (set); -} - -# define gl_oset_search gl_oset_search_inline -static inline bool -gl_oset_search (gl_oset_t set, const void *elt) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt); -} - -# define gl_oset_search_atleast gl_oset_search_atleast_inline -static inline bool -gl_oset_search_atleast (gl_oset_t set, - gl_setelement_threshold_fn threshold_fn, - const void *threshold, const void **eltp) -{ - return ((const struct gl_oset_impl_base *) set)->vtable - ->search_atleast (set, threshold_fn, threshold, eltp); -} - -# define gl_oset_add gl_oset_add_inline -static inline bool -gl_oset_add (gl_oset_t set, const void *elt) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->add (set, elt); -} - -# define gl_oset_remove gl_oset_remove_inline -static inline bool -gl_oset_remove (gl_oset_t set, const void *elt) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->remove (set, elt); -} - -# define gl_oset_free gl_oset_free_inline -static inline void -gl_oset_free (gl_oset_t set) -{ - ((const struct gl_oset_impl_base *) set)->vtable->oset_free (set); -} - -# define gl_oset_iterator gl_oset_iterator_inline -static inline gl_oset_iterator_t -gl_oset_iterator (gl_oset_t set) -{ - return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set); -} - -# define gl_oset_iterator_next gl_oset_iterator_next_inline -static inline bool -gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp) -{ - return iterator->vtable->iterator_next (iterator, eltp); -} - -# define gl_oset_iterator_free gl_oset_iterator_free_inline -static inline void -gl_oset_iterator_free (gl_oset_iterator_t *iterator) -{ - iterator->vtable->iterator_free (iterator); -} - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _GL_OSET_H */ diff --git a/src/bin/m4/lib/malloc.c b/src/bin/m4/lib/malloc.c deleted file mode 100644 index d4dae3e182..0000000000 --- a/src/bin/m4/lib/malloc.c +++ /dev/null @@ -1,35 +0,0 @@ -/* malloc() function that is glibc compatible. - - Copyright (C) 1997, 1998, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* written by Jim Meyering */ - -#include -#undef malloc - -#include - -/* Allocate an N-byte block of memory from the heap. - If N is zero, allocate a 1-byte block. */ - -void * -rpl_malloc (size_t n) -{ - if (n == 0) - n = 1; - return malloc (n); -} diff --git a/src/bin/m4/lib/mbchar.c b/src/bin/m4/lib/mbchar.c deleted file mode 100644 index 95373f58ba..0000000000 --- a/src/bin/m4/lib/mbchar.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2001, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -#include - -#include - -#include "mbchar.h" - -#if IS_BASIC_ASCII - -/* Bit table of characters in the ISO C "basic character set". */ -const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] = -{ - 0x00001a00, /* '\t' '\v' '\f' */ - 0xffffffef, /* ' '...'#' '%'...'?' */ - 0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */ - 0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */ - /* The remaining bits are 0. */ -}; - -#endif /* IS_BASIC_ASCII */ diff --git a/src/bin/m4/lib/mbchar.h b/src/bin/m4/lib/mbchar.h deleted file mode 100644 index a0c2cdcb99..0000000000 --- a/src/bin/m4/lib/mbchar.h +++ /dev/null @@ -1,478 +0,0 @@ -/* Multibyte character data type. - Copyright (C) 2001, 2005-2006 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 2, 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, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Written by Bruno Haible . */ - -/* A multibyte character is a short subsequence of a char* string, - representing a single wide character. - - We use multibyte characters instead of wide characters because of - the following goals: - 1) correct multibyte handling, i.e. operate according to the LC_CTYPE - locale, - 2) ease of maintenance, i.e. the maintainer needs not know all details - of the ISO C 99 standard, - 3) don't fail grossly if the input is not in the encoding set by the - locale, because often different encodings are in use in the same - countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...), - 4) fast in the case of ASCII characters, - 5) portability, i.e. don't make unportable assumptions about wchar_t. - - Multibyte characters are only accessed through the mb* macros. - - mb_ptr (mbc) - return a pointer to the beginning of the multibyte sequence. - - mb_len (mbc) - returns the number of bytes occupied by the multibyte sequence. - Always > 0. - - mb_iseq (mbc, sc) - returns true if mbc is the standard ASCII character sc. - - mb_isnul (mbc) - returns true if mbc is the nul character. - - mb_cmp (mbc1, mbc2) - returns a positive, zero, or negative value depending on whether mbc1 - sorts after, same or before mbc2. - - mb_casecmp (mbc1, mbc2) - returns a positive, zero, or negative value depending on whether mbc1 - sorts after, same or before mbc2, modulo upper/lowercase conversion. - - mb_equal (mbc1, mbc2) - returns true if mbc1 and mbc2 are equal. - - mb_caseequal (mbc1, mbc2) - returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion. - - mb_isalnum (mbc) - returns true if mbc is alphanumeric. - - mb_isalpha (mbc) - returns true if mbc is alphabetic. - - mb_isascii(mbc) - returns true if mbc is plain ASCII. - - mb_isblank (mbc) - returns true if mbc is a blank. - - mb_iscntrl (mbc) - returns true if mbc is a control character. - - mb_isdigit (mbc) - returns true if mbc is a decimal digit. - - mb_isgraph (mbc) - returns true if mbc is a graphic character. - - mb_islower (mbc) - returns true if mbc is lowercase. - - mb_isprint (mbc) - returns true if mbc is a printable character. - - mb_ispunct (mbc) - returns true if mbc is a punctuation character. - - mb_isspace (mbc) - returns true if mbc is a space character. - - mb_isupper (mbc) - returns true if mbc is uppercase. - - mb_isxdigit (mbc) - returns true if mbc is a hexadecimal digit. - - mb_width (mbc) - returns the number of columns on the output device occupied by mbc. - Always >= 0. - - mb_putc (mbc, stream) - outputs mbc on stream, a byte oriented FILE stream opened for output. - - mb_setascii (&mbc, sc) - assigns the standard ASCII character sc to mbc. - - mb_copy (&destmbc, &srcmbc) - copies srcmbc to destmbc. - - Here are the function prototypes of the macros. - - extern const char * mb_ptr (const mbchar_t mbc); - extern size_t mb_len (const mbchar_t mbc); - extern bool mb_iseq (const mbchar_t mbc, char sc); - extern bool mb_isnul (const mbchar_t mbc); - extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2); - extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2); - extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2); - extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2); - extern bool mb_isalnum (const mbchar_t mbc); - extern bool mb_isalpha (const mbchar_t mbc); - extern bool mb_isascii (const mbchar_t mbc); - extern bool mb_isblank (const mbchar_t mbc); - extern bool mb_iscntrl (const mbchar_t mbc); - extern bool mb_isdigit (const mbchar_t mbc); - extern bool mb_isgraph (const mbchar_t mbc); - extern bool mb_islower (const mbchar_t mbc); - extern bool mb_isprint (const mbchar_t mbc); - extern bool mb_ispunct (const mbchar_t mbc); - extern bool mb_isspace (const mbchar_t mbc); - extern bool mb_isupper (const mbchar_t mbc); - extern bool mb_isxdigit (const mbchar_t mbc); - extern int mb_width (const mbchar_t mbc); - extern void mb_putc (const mbchar_t mbc, FILE *stream); - extern void mb_setascii (mbchar_t *new, char sc); - extern void mb_copy (mbchar_t *new, const mbchar_t *old); - */ - -#ifndef _MBCHAR_H -#define _MBCHAR_H 1 - -#include -#include - -/* Tru64 with Desktop Toolkit C has a bug: must be included before - . - BSD/OS 4.1 has a bug: and must be included before - . */ -#include -#include -#include - -/* BeOS 5 has the functions but no . */ -#if HAVE_WCTYPE_H -# include -#endif -/* FreeBSD 4.4 to 4.11 has but lacks the functions. - Assume all 12 functions are implemented the same way, or not at all. */ -#if !defined iswalnum && !HAVE_ISWCNTRL -static inline int -iswalnum (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? (wc >= '0' && wc <= '9') || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z') - : 0); -} -# define iswalnum iswalnum -#endif -#if !defined iswalpha && !HAVE_ISWCNTRL -static inline int -iswalpha (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z' - : 0); -} -# define iswalpha iswalpha -#endif -#if !defined iswblank && !HAVE_ISWCNTRL -static inline int -iswblank (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc == ' ' || wc == '\t' - : 0); -} -# define iswblank iswblank -#endif -#if !defined iswcntrl && !HAVE_ISWCNTRL -static inline int -iswcntrl (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? (wc & ~0x1f) == 0 || wc == 0x7f - : 0); -} -# define iswcntrl iswcntrl -#endif -#if !defined iswdigit && !HAVE_ISWCNTRL -static inline int -iswdigit (wint_t wc) -{ - return (wc >= '0' && wc <= '9'); -} -# define iswdigit iswdigit -#endif -#if !defined iswgraph && !HAVE_ISWCNTRL -static inline int -iswgraph (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc >= '!' && wc <= '~' - : 1); -} -# define iswgraph iswgraph -#endif -#if !defined iswlower && !HAVE_ISWCNTRL -static inline int -iswlower (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc >= 'a' && wc <= 'z' - : 0); -} -# define iswlower iswlower -#endif -#if !defined iswprint && !HAVE_ISWCNTRL -static inline int -iswprint (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc >= ' ' && wc <= '~' - : 1); -} -# define iswprint iswprint -#endif -#if !defined iswpunct && !HAVE_ISWCNTRL -static inline int -iswpunct (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc >= '!' && wc <= '~' - && !((wc >= '0' && wc <= '9') - || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')) - : 1); -} -# define iswpunct iswpunct -#endif -#if !defined iswspace && !HAVE_ISWCNTRL -static inline int -iswspace (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc == ' ' || wc == '\t' - || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r' - : 0); -} -# define iswspace iswspace -#endif -#if !defined iswupper && !HAVE_ISWCNTRL -static inline int -iswupper (wint_t wc) -{ - return (wc >= 0 && wc < 128 - ? wc >= 'A' && wc <= 'Z' - : 0); -} -# define iswupper iswupper -#endif -#if !defined iswxdigit && !HAVE_ISWCNTRL -static inline int -iswxdigit (wint_t wc) -{ - return (wc >= '0' && wc <= '9') || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F'); -} -# define iswxdigit iswxdigit -#endif - -#include "wcwidth.h" - -#define MBCHAR_BUF_SIZE 24 - -struct mbchar -{ - const char *ptr; /* pointer to current character */ - size_t bytes; /* number of bytes of current character, > 0 */ - bool wc_valid; /* true if wc is a valid wide character */ - wchar_t wc; /* if wc_valid: the current character */ - char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */ -}; - -/* EOF (not a real character) is represented with bytes = 0 and - wc_valid = false. */ - -typedef struct mbchar mbchar_t; - -/* Access the current character. */ -#define mb_ptr(mbc) ((mbc).ptr) -#define mb_len(mbc) ((mbc).bytes) - -/* Comparison of characters. */ -#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc)) -#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0) -#define mb_cmp(mbc1, mbc2) \ - ((mbc1).wc_valid \ - ? ((mbc2).wc_valid \ - ? (int) (mbc1).wc - (int) (mbc2).wc \ - : -1) \ - : ((mbc2).wc_valid \ - ? 1 \ - : (mbc1).bytes == (mbc2).bytes \ - ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ - : (mbc1).bytes < (mbc2).bytes \ - ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ - : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) -#define mb_casecmp(mbc1, mbc2) \ - ((mbc1).wc_valid \ - ? ((mbc2).wc_valid \ - ? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \ - : -1) \ - : ((mbc2).wc_valid \ - ? 1 \ - : (mbc1).bytes == (mbc2).bytes \ - ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ - : (mbc1).bytes < (mbc2).bytes \ - ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ - : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) -#define mb_equal(mbc1, mbc2) \ - ((mbc1).wc_valid && (mbc2).wc_valid \ - ? (mbc1).wc == (mbc2).wc \ - : (mbc1).bytes == (mbc2).bytes \ - && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) -#define mb_caseequal(mbc1, mbc2) \ - ((mbc1).wc_valid && (mbc2).wc_valid \ - ? towlower ((mbc1).wc) == towlower ((mbc2).wc) \ - : (mbc1).bytes == (mbc2).bytes \ - && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) - -/* , classification. */ -#define mb_isascii(mbc) \ - ((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127) -#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc)) -#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc)) -#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc)) -#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc)) -#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc)) -#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc)) -#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc)) -#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc)) -#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc)) -#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc)) -#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc)) -#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc)) - -/* Extra function. */ - -/* Unprintable characters appear as a small box of width 1. */ -#define MB_UNPRINTABLE_WIDTH 1 - -static inline int -mb_width_aux (wint_t wc) -{ - int w = wcwidth (wc); - /* For unprintable characters, arbitrarily return 0 for control characters - and MB_UNPRINTABLE_WIDTH otherwise. */ - return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH); -} - -#define mb_width(mbc) \ - ((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH) - -/* Output. */ -#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream)) - -/* Assignment. */ -#define mb_setascii(mbc, sc) \ - ((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \ - (mbc)->wc = (mbc)->buf[0] = (sc)) - -/* Copying a character. */ -static inline void -mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc) -{ - if (old_mbc->ptr == &old_mbc->buf[0]) - { - memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes); - new_mbc->ptr = &new_mbc->buf[0]; - } - else - new_mbc->ptr = old_mbc->ptr; - new_mbc->bytes = old_mbc->bytes; - if ((new_mbc->wc_valid = old_mbc->wc_valid)) - new_mbc->wc = old_mbc->wc; -} - - -/* is_basic(c) tests whether the single-byte character c is in the - ISO C "basic character set". - This is a convenience function, and is in this file only to share code - between mbiter_multi.h and mbfile_multi.h. */ -#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ - && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ - && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ - && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ - && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ - && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ - && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ - && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ - && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ - && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ - && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ - && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ - && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ - && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ - && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ - && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ - && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ - && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ - && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ - && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ - && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ - && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ - && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) -/* The character set is ISO-646, not EBCDIC. */ -# define IS_BASIC_ASCII 1 - -extern const unsigned int is_basic_table[]; - -static inline bool -is_basic (char c) -{ - return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31)) - & 1; -} - -#else - -static inline bool -is_basic (char c) -{ - switch (c) - { - case '\t': case '\v': case '\f': - case ' ': case '!': case '"': case '#': case '%': - case '&': case '\'': case '(': case ')': case '*': - case '+': case ',': case '-': case '.': case '/': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case ':': case ';': case '<': case '=': case '>': - case '?': - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case '[': case '\\': case ']': case '^': case '_': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': case '{': case '|': case '}': case '~': - return 1; - default: - return 0; - } -} - -#endif - -#endif /* _MBCHAR_H */ diff --git a/src/bin/m4/lib/mbuiter.h b/src/bin/m4/lib/mbuiter.h deleted file mode 100644 index 9da3a6c79c..0000000000 --- a/src/bin/m4/lib/mbuiter.h +++ /dev/null @@ -1,203 +0,0 @@ -/* Iterating through multibyte strings: macros for multi-byte encodings. - Copyright (C) 2001, 2005 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 2, 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, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Written by Bruno Haible . */ - -/* The macros in this file implement forward iteration through a - multi-byte string, without knowing its length a-priori. - - With these macros, an iteration loop that looks like - - char *iter; - for (iter = buf; *iter != '\0'; iter++) - { - do_something (*iter); - } - - becomes - - mbui_iterator_t iter; - for (mbui_init (iter, buf); mbui_avail (iter); mbui_advance (iter)) - { - do_something (mbui_cur_ptr (iter), mb_len (mbui_cur (iter))); - } - - The benefit of these macros over plain use of mbrtowc is: - - Handling of invalid multibyte sequences is possible without - making the code more complicated, while still preserving the - invalid multibyte sequences. - - Compared to mbiter.h, the macros here don't need to know the string's - length a-priori. The downside is that at each step, the look-ahead - that guards against overrunning the terminating '\0' is more expensive. - The mbui_* macros are therefore suitable when there is a high probability - that only the first few multibyte characters need to be inspected. - Whereas the mbi_* macros are better if usually the iteration runs - through the entire string. - - mbui_iterator_t - is a type usable for variable declarations. - - mbui_init (iter, startptr) - initializes the iterator, starting at startptr. - - mbui_avail (iter) - returns true if there are more multibyte chracters available before - the end of string is reached. In this case, mbui_cur (iter) is - initialized to the next multibyte chracter. - - mbui_advance (iter) - advances the iterator by one multibyte character. - - mbui_cur (iter) - returns the current multibyte character, of type mbchar_t. All the - macros defined in mbchar.h can be used on it. - - mbui_cur_ptr (iter) - return a pointer to the beginning of the current multibyte character. - - mbui_reloc (iter, ptrdiff) - relocates iterator when the string is moved by ptrdiff bytes. - - Here are the function prototypes of the macros. - - extern void mbui_init (mbui_iterator_t iter, const char *startptr); - extern bool mbui_avail (mbui_iterator_t iter); - extern void mbui_advance (mbui_iterator_t iter); - extern mbchar_t mbui_cur (mbui_iterator_t iter); - extern const char * mbui_cur_ptr (mbui_iterator_t iter); - extern void mbui_reloc (mbui_iterator_t iter, ptrdiff_t ptrdiff); - */ - -#ifndef _MBUITER_H -#define _MBUITER_H 1 - -#include -#include -#include - -/* Tru64 with Desktop Toolkit C has a bug: must be included before - . - BSD/OS 4.1 has a bug: and must be included before - . */ -#include -#include -#include - -#include "mbchar.h" -#include "strnlen1.h" - -struct mbuiter_multi -{ - bool in_shift; /* true if next byte may not be interpreted as ASCII */ - mbstate_t state; /* if in_shift: current shift state */ - bool next_done; /* true if mbui_avail has already filled the following */ - struct mbchar cur; /* the current character: - const char *cur.ptr pointer to current character - The following are only valid after mbui_avail. - size_t cur.bytes number of bytes of current character - bool cur.wc_valid true if wc is a valid wide character - wchar_t cur.wc if wc_valid: the current character - */ -}; - -static inline void -mbuiter_multi_next (struct mbuiter_multi *iter) -{ - if (iter->next_done) - return; - if (iter->in_shift) - goto with_shift; - /* Handle most ASCII characters quickly, without calling mbrtowc(). */ - if (is_basic (*iter->cur.ptr)) - { - /* These characters are part of the basic character set. ISO C 99 - guarantees that their wide character code is identical to their - char code. */ - iter->cur.bytes = 1; - iter->cur.wc = *iter->cur.ptr; - iter->cur.wc_valid = true; - } - else - { - assert (mbsinit (&iter->state)); - iter->in_shift = true; - with_shift: - iter->cur.bytes = mbrtowc (&iter->cur.wc, iter->cur.ptr, - strnlen1 (iter->cur.ptr, MB_CUR_MAX), - &iter->state); - if (iter->cur.bytes == (size_t) -1) - { - /* An invalid multibyte sequence was encountered. */ - iter->cur.bytes = 1; - iter->cur.wc_valid = false; - /* Whether to set iter->in_shift = false and reset iter->state - or not is not very important; the string is bogus anyway. */ - } - else if (iter->cur.bytes == (size_t) -2) - { - /* An incomplete multibyte character at the end. */ - iter->cur.bytes = strlen (iter->cur.ptr); - iter->cur.wc_valid = false; - /* Whether to set iter->in_shift = false and reset iter->state - or not is not important; the string end is reached anyway. */ - } - else - { - if (iter->cur.bytes == 0) - { - /* A null wide character was encountered. */ - iter->cur.bytes = 1; - assert (*iter->cur.ptr == '\0'); - assert (iter->cur.wc == 0); - } - iter->cur.wc_valid = true; - - /* When in the initial state, we can go back treating ASCII - characters more quickly. */ - if (mbsinit (&iter->state)) - iter->in_shift = false; - } - } - iter->next_done = true; -} - -static inline void -mbuiter_multi_reloc (struct mbuiter_multi *iter, ptrdiff_t ptrdiff) -{ - iter->cur.ptr += ptrdiff; -} - -/* Iteration macros. */ -typedef struct mbuiter_multi mbui_iterator_t; -#define mbui_init(iter, startptr) \ - ((iter).cur.ptr = (startptr), \ - (iter).in_shift = false, memset (&(iter).state, '\0', sizeof (mbstate_t)), \ - (iter).next_done = false) -#define mbui_avail(iter) \ - (mbuiter_multi_next (&(iter)), !mb_isnul ((iter).cur)) -#define mbui_advance(iter) \ - ((iter).cur.ptr += (iter).cur.bytes, (iter).next_done = false) - -/* Access to the current character. */ -#define mbui_cur(iter) (iter).cur -#define mbui_cur_ptr(iter) (iter).cur.ptr - -/* Relocation. */ -#define mbui_reloc(iter, ptrdiff) mbuiter_multi_reloc (&iter, ptrdiff) - -#endif /* _MBUITER_H */ diff --git a/src/bin/m4/lib/memchr.c b/src/bin/m4/lib/memchr.c deleted file mode 100644 index d44ad6deb5..0000000000 --- a/src/bin/m4/lib/memchr.c +++ /dev/null @@ -1,201 +0,0 @@ -/* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006 Free - Software Foundation, Inc. - - Based on strlen implementation by Torbjorn Granlund (tege@sics.se), - with help from Dan Sahlin (dan@sics.se) and - commentary by Jim Blandy (jimb@ai.mit.edu); - adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), - and implemented by Roland McGrath (roland@ai.mit.edu). - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@prep.ai.mit.edu. - -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 2, 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, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBC -# include -#endif - -#include - -#include - -#if defined _LIBC -# include -#else -# define reg_char char -#endif - -#include - -#if HAVE_BP_SYM_H || defined _LIBC -# include -#else -# define BP_SYM(sym) sym -#endif - -#undef memchr -#undef __memchr - -/* Search no more than N bytes of S for C. */ -void * -__memchr (void const *s, int c_in, size_t n) -{ - const unsigned char *char_ptr; - const unsigned long int *longword_ptr; - unsigned long int longword, magic_bits, charmask; - unsigned reg_char c; - int i; - - c = (unsigned char) c_in; - - /* Handle the first few characters by reading one character at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; - n > 0 && (size_t) char_ptr % sizeof longword != 0; - --n, ++char_ptr) - if (*char_ptr == c) - return (void *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to any size longwords. */ - - longword_ptr = (const unsigned long int *) char_ptr; - - /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits - the "holes." Note that there is a hole just to the left of - each byte, with an extra at the end: - - bits: 01111110 11111110 11111110 11111111 - bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD - - The 1-bits make sure that carries propagate to the next 0-bit. - The 0-bits provide holes for carries to fall into. */ - - /* Set MAGIC_BITS to be this pattern of 1 and 0 bits. - Set CHARMASK to be a longword, each of whose bytes is C. */ - - magic_bits = 0xfefefefe; - charmask = c | (c << 8); - charmask |= charmask << 16; -#if 0xffffffffU < ULONG_MAX - magic_bits |= magic_bits << 32; - charmask |= charmask << 32; - if (8 < sizeof longword) - for (i = 64; i < sizeof longword * 8; i *= 2) - { - magic_bits |= magic_bits << i; - charmask |= charmask << i; - } -#endif - magic_bits = (ULONG_MAX >> 1) & (magic_bits | 1); - - /* Instead of the traditional loop which tests each character, - we will test a longword at a time. The tricky part is testing - if *any of the four* bytes in the longword in question are zero. */ - while (n >= sizeof longword) - { - /* We tentatively exit the loop if adding MAGIC_BITS to - LONGWORD fails to change any of the hole bits of LONGWORD. - - 1) Is this safe? Will it catch all the zero bytes? - Suppose there is a byte with all zeros. Any carry bits - propagating from its left will fall into the hole at its - least significant bit and stop. Since there will be no - carry from its most significant bit, the LSB of the - byte to the left will be unchanged, and the zero will be - detected. - - 2) Is this worthwhile? Will it ignore everything except - zero bytes? Suppose every byte of LONGWORD has a bit set - somewhere. There will be a carry into bit 8. If bit 8 - is set, this will carry into bit 16. If bit 8 is clear, - one of bits 9-15 must be set, so there will be a carry - into bit 16. Similarly, there will be a carry into bit - 24. If one of bits 24-30 is set, there will be a carry - into bit 31, so all of the hole bits will be changed. - - The one misfire occurs when bits 24-30 are clear and bit - 31 is set; in this case, the hole at bit 31 is not - changed. If we had access to the processor carry flag, - we could close this loophole by putting the fourth hole - at bit 32! - - So it ignores everything except 128's, when they're aligned - properly. - - 3) But wait! Aren't we looking for C, not zero? - Good point. So what we do is XOR LONGWORD with a longword, - each of whose bytes is C. This turns each byte that is C - into a zero. */ - - longword = *longword_ptr++ ^ charmask; - - /* Add MAGIC_BITS to LONGWORD. */ - if ((((longword + magic_bits) - - /* Set those bits that were unchanged by the addition. */ - ^ ~longword) - - /* Look at only the hole bits. If any of the hole bits - are unchanged, most likely one of the bytes was a - zero. */ - & ~magic_bits) != 0) - { - /* Which of the bytes was C? If none of them were, it was - a misfire; continue the search. */ - - const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); - - if (cp[0] == c) - return (void *) cp; - if (cp[1] == c) - return (void *) &cp[1]; - if (cp[2] == c) - return (void *) &cp[2]; - if (cp[3] == c) - return (void *) &cp[3]; - if (4 < sizeof longword && cp[4] == c) - return (void *) &cp[4]; - if (5 < sizeof longword && cp[5] == c) - return (void *) &cp[5]; - if (6 < sizeof longword && cp[6] == c) - return (void *) &cp[6]; - if (7 < sizeof longword && cp[7] == c) - return (void *) &cp[7]; - if (8 < sizeof longword) - for (i = 8; i < sizeof longword; i++) - if (cp[i] == c) - return (void *) &cp[i]; - } - - n -= sizeof longword; - } - - char_ptr = (const unsigned char *) longword_ptr; - - while (n-- > 0) - { - if (*char_ptr == c) - return (void *) char_ptr; - else - ++char_ptr; - } - - return 0; -} -#ifdef weak_alias -weak_alias (__memchr, BP_SYM (memchr)) -#endif diff --git a/src/bin/m4/lib/mkdtemp.c b/src/bin/m4/lib/mkdtemp.c deleted file mode 100644 index e916d385b1..0000000000 --- a/src/bin/m4/lib/mkdtemp.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 1999, 2001-2003, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Extracted from misc/mkdtemp.c. */ - -#include - -/* Specification. */ -#include "mkdtemp.h" - -#include "tempname.h" -#include - -/* Generate a unique temporary directory from TEMPLATE. - The last six characters of TEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the filename unique. - The directory is created, mode 700, and its name is returned. - (This function comes from OpenBSD.) */ -char * -mkdtemp (char *template) -{ - if (gen_tempname (template, GT_DIR)) - return NULL; - else - return template; -} diff --git a/src/bin/m4/lib/mkdtemp.h b/src/bin/m4/lib/mkdtemp.h deleted file mode 100644 index 6176048019..0000000000 --- a/src/bin/m4/lib/mkdtemp.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Creating a private temporary directory. - Copyright (C) 2001-2002 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#if HAVE_MKDTEMP - -/* Get mkdtemp() declaration. */ -#include - -#else - -/* Create a unique temporary directory from TEMPLATE. - The last six characters of TEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the directory name unique. - Returns TEMPLATE, or a null pointer if it cannot get a unique name. - The directory is created mode 700. */ -extern char * mkdtemp (char *template); - -#endif diff --git a/src/bin/m4/lib/mkstemp-safer.c b/src/bin/m4/lib/mkstemp-safer.c deleted file mode 100644 index c8c5bbd6e4..0000000000 --- a/src/bin/m4/lib/mkstemp-safer.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Invoke mkstemp, but avoid some glitches. - - Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include - -#include "stdlib-safer.h" - -#include "mkstemp.h" -#include "unistd-safer.h" - -/* Like mkstemp, but do not return STDIN_FILENO, STDOUT_FILENO, or - STDERR_FILENO. */ - -int -mkstemp_safer (char *templ) -{ - return fd_safer (mkstemp (templ)); -} diff --git a/src/bin/m4/lib/mkstemp.c b/src/bin/m4/lib/mkstemp.c deleted file mode 100644 index 34c9e474c0..0000000000 --- a/src/bin/m4/lib/mkstemp.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (C) 1998, 1999, 2001, 2005, 2006 Free Software Foundation, Inc. - This file is derived from the one in the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#if !_LIBC -# include -# include "mkstemp.h" -# include "tempname.h" -# define __gen_tempname gen_tempname -# define __GT_FILE GT_FILE -#endif - -#include -#include - -#ifndef __GT_FILE -# define __GT_FILE 0 -#endif - -/* Generate a unique temporary file name from TEMPLATE. - The last six characters of TEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the file name unique. - Then open the file and return a fd. */ -int -mkstemp (template) - char *template; -{ - return __gen_tempname (template, __GT_FILE); -} diff --git a/src/bin/m4/lib/mkstemp.h b/src/bin/m4/lib/mkstemp.h deleted file mode 100644 index 9ed74116d2..0000000000 --- a/src/bin/m4/lib/mkstemp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Create a unique temporary file. - - Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* written by Jim Meyering */ - -#include -#include - -#ifdef __MKSTEMP_PREFIX -# define _GL_CONCAT(x, y) x ## y -# define _GL_XCONCAT(x, y) _GL_CONCAT (x, y) -# define __MKSTEMP_ID(y) _GL_XCONCAT (__MKSTEMP_PREFIX, y) -# undef mkstemp -# define mkstemp __MKSTEMP_ID (mkstemp) -int mkstemp (char *); -#endif diff --git a/src/bin/m4/lib/obstack.c b/src/bin/m4/lib/obstack.c deleted file mode 100644 index 5cd0b7a6d0..0000000000 --- a/src/bin/m4/lib/obstack.c +++ /dev/null @@ -1,431 +0,0 @@ -/* obstack.c - subroutines used implicitly by object stack macros - - Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifdef _LIBC -# include -# include -#else -# include -# include "obstack.h" -#endif - -/* NOTE BEFORE MODIFYING THIS FILE: This version number must be - incremented whenever callers compiled using an old obstack.h can no - longer properly call the functions in this obstack.c. */ -#define OBSTACK_INTERFACE_VERSION 1 - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself, and the installed library - supports the same library interface we do. This code is part of the GNU - C Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object - files, it is simpler to just do this in the source for each such file. */ - -#include /* Random thing to get __GNU_LIBRARY__. */ -#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 -# include -# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#include - -#ifndef ELIDE_CODE - -# include - -/* Determine default alignment. */ -union fooround -{ - uintmax_t i; - long double d; - void *p; -}; -struct fooalign -{ - char c; - union fooround u; -}; -/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. - But in fact it might be less smart and round addresses to as much as - DEFAULT_ROUNDING. So we prepare for it to do that. */ -enum - { - DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), - DEFAULT_ROUNDING = sizeof (union fooround) - }; - -/* When we copy a long block of data, this is the unit to do it with. - On some machines, copying successive ints does not work; - in such a case, redefine COPYING_UNIT to `long' (if that works) - or `char' as a last resort. */ -# ifndef COPYING_UNIT -# define COPYING_UNIT int -# endif - - -/* The functions allocating more room by calling `obstack_chunk_alloc' - jump to the handler pointed to by `obstack_alloc_failed_handler'. - This can be set to a user defined function which should either - abort gracefully or use longjump - but shouldn't return. This - variable by default points to the internal function - `print_and_abort'. */ -static void print_and_abort (void); -void (*obstack_alloc_failed_handler) (void) = print_and_abort; - -/* Exit value used when `print_and_abort' is used. */ -# include -# ifdef _LIBC -int obstack_exit_failure = EXIT_FAILURE; -# else -# include "exitfail.h" -# define obstack_exit_failure exit_failure -# endif - -# ifdef _LIBC -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -/* A looong time ago (before 1994, anyway; we're not sure) this global variable - was used by non-GNU-C macros to avoid multiple evaluation. The GNU C - library still exports it because somebody might use it. */ -struct obstack *_obstack_compat; -compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); -# endif -# endif - -/* Define a macro that either calls functions with the traditional malloc/free - calling interface, or calls functions with the mmalloc/mfree interface - (that adds an extra first argument), based on the state of use_extra_arg. - For free, do not use ?:, since some compilers, like the MIPS compilers, - do not allow (expr) ? void : void. */ - -# define CALL_CHUNKFUN(h, size) \ - (((h) -> use_extra_arg) \ - ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ - : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) - -# define CALL_FREEFUN(h, old_chunk) \ - do { \ - if ((h) -> use_extra_arg) \ - (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ - else \ - (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ - } while (0) - - -/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). - Objects start on multiples of ALIGNMENT (0 means use default). - CHUNKFUN is the function to use to allocate chunks, - and FREEFUN the function to free them. - - Return nonzero if successful, calls obstack_alloc_failed_handler if - allocation fails. */ - -int -_obstack_begin (struct obstack *h, - int size, int alignment, - void *(*chunkfun) (long), - void (*freefun) (void *)) -{ - register struct _obstack_chunk *chunk; /* points to new chunk */ - - if (alignment == 0) - alignment = DEFAULT_ALIGNMENT; - if (size == 0) - /* Default size is what GNU malloc can fit in a 4096-byte block. */ - { - /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. - Use the values for range checking, because if range checking is off, - the extra bytes won't be missed terribly, but if range checking is on - and we used a larger request, a whole extra 4096 bytes would be - allocated. - - These number are irrelevant to the new GNU malloc. I suspect it is - less sensitive to the size of the request. */ - int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) - + 4 + DEFAULT_ROUNDING - 1) - & ~(DEFAULT_ROUNDING - 1)); - size = 4096 - extra; - } - - h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; - h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; - h->chunk_size = size; - h->alignment_mask = alignment - 1; - h->use_extra_arg = 0; - - chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); - if (!chunk) - (*obstack_alloc_failed_handler) (); - h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, - alignment - 1); - h->chunk_limit = chunk->limit - = (char *) chunk + h->chunk_size; - chunk->prev = 0; - /* The initial chunk now contains no empty object. */ - h->maybe_empty_object = 0; - h->alloc_failed = 0; - return 1; -} - -int -_obstack_begin_1 (struct obstack *h, int size, int alignment, - void *(*chunkfun) (void *, long), - void (*freefun) (void *, void *), - void *arg) -{ - register struct _obstack_chunk *chunk; /* points to new chunk */ - - if (alignment == 0) - alignment = DEFAULT_ALIGNMENT; - if (size == 0) - /* Default size is what GNU malloc can fit in a 4096-byte block. */ - { - /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. - Use the values for range checking, because if range checking is off, - the extra bytes won't be missed terribly, but if range checking is on - and we used a larger request, a whole extra 4096 bytes would be - allocated. - - These number are irrelevant to the new GNU malloc. I suspect it is - less sensitive to the size of the request. */ - int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) - + 4 + DEFAULT_ROUNDING - 1) - & ~(DEFAULT_ROUNDING - 1)); - size = 4096 - extra; - } - - h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; - h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; - h->chunk_size = size; - h->alignment_mask = alignment - 1; - h->extra_arg = arg; - h->use_extra_arg = 1; - - chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); - if (!chunk) - (*obstack_alloc_failed_handler) (); - h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, - alignment - 1); - h->chunk_limit = chunk->limit - = (char *) chunk + h->chunk_size; - chunk->prev = 0; - /* The initial chunk now contains no empty object. */ - h->maybe_empty_object = 0; - h->alloc_failed = 0; - return 1; -} - -/* Allocate a new current chunk for the obstack *H - on the assumption that LENGTH bytes need to be added - to the current object, or a new object of length LENGTH allocated. - Copies any partial object from the end of the old chunk - to the beginning of the new one. */ - -void -_obstack_newchunk (struct obstack *h, int length) -{ - register struct _obstack_chunk *old_chunk = h->chunk; - register struct _obstack_chunk *new_chunk; - register long new_size; - register long obj_size = h->next_free - h->object_base; - register long i; - long already; - char *object_base; - - /* Compute size for new chunk. */ - new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100; - if (new_size < h->chunk_size) - new_size = h->chunk_size; - - /* Allocate and initialize the new chunk. */ - new_chunk = CALL_CHUNKFUN (h, new_size); - if (!new_chunk) - (*obstack_alloc_failed_handler) (); - h->chunk = new_chunk; - new_chunk->prev = old_chunk; - new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; - - /* Compute an aligned object_base in the new chunk */ - object_base = - __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); - - /* Move the existing object to the new chunk. - Word at a time is fast and is safe if the object - is sufficiently aligned. */ - if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) - { - for (i = obj_size / sizeof (COPYING_UNIT) - 1; - i >= 0; i--) - ((COPYING_UNIT *)object_base)[i] - = ((COPYING_UNIT *)h->object_base)[i]; - /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, - but that can cross a page boundary on a machine - which does not do strict alignment for COPYING_UNITS. */ - already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); - } - else - already = 0; - /* Copy remaining bytes one by one. */ - for (i = already; i < obj_size; i++) - object_base[i] = h->object_base[i]; - - /* If the object just copied was the only data in OLD_CHUNK, - free that chunk and remove it from the chain. - But not if that chunk might contain an empty object. */ - if (! h->maybe_empty_object - && (h->object_base - == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, - h->alignment_mask))) - { - new_chunk->prev = old_chunk->prev; - CALL_FREEFUN (h, old_chunk); - } - - h->object_base = object_base; - h->next_free = h->object_base + obj_size; - /* The new chunk certainly contains no empty object yet. */ - h->maybe_empty_object = 0; -} -# ifdef _LIBC -libc_hidden_def (_obstack_newchunk) -# endif - -/* Return nonzero if object OBJ has been allocated from obstack H. - This is here for debugging. - If you use it in a program, you are probably losing. */ - -/* Suppress -Wmissing-prototypes warning. We don't want to declare this in - obstack.h because it is just for debugging. */ -int _obstack_allocated_p (struct obstack *h, void *obj); - -int -_obstack_allocated_p (struct obstack *h, void *obj) -{ - register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ - register struct _obstack_chunk *plp; /* point to previous chunk if any */ - - lp = (h)->chunk; - /* We use >= rather than > since the object cannot be exactly at - the beginning of the chunk but might be an empty object exactly - at the end of an adjacent chunk. */ - while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) - { - plp = lp->prev; - lp = plp; - } - return lp != 0; -} - -/* Free objects in obstack H, including OBJ and everything allocate - more recently than OBJ. If OBJ is zero, free everything in H. */ - -# undef obstack_free - -void -__obstack_free (struct obstack *h, void *obj) -{ - register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ - register struct _obstack_chunk *plp; /* point to previous chunk if any */ - - lp = h->chunk; - /* We use >= because there cannot be an object at the beginning of a chunk. - But there can be an empty object at that address - at the end of another chunk. */ - while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) - { - plp = lp->prev; - CALL_FREEFUN (h, lp); - lp = plp; - /* If we switch chunks, we can't tell whether the new current - chunk contains an empty object, so assume that it may. */ - h->maybe_empty_object = 1; - } - if (lp) - { - h->object_base = h->next_free = (char *) (obj); - h->chunk_limit = lp->limit; - h->chunk = lp; - } - else if (obj != 0) - /* obj is not in any of the chunks! */ - abort (); -} - -# ifdef _LIBC -/* Older versions of libc used a function _obstack_free intended to be - called by non-GCC compilers. */ -strong_alias (obstack_free, _obstack_free) -# endif - -int -_obstack_memory_used (struct obstack *h) -{ - register struct _obstack_chunk* lp; - register int nbytes = 0; - - for (lp = h->chunk; lp != 0; lp = lp->prev) - { - nbytes += lp->limit - (char *) lp; - } - return nbytes; -} - -/* Define the error handler. */ -# ifdef _LIBC -# include -# else -# include "gettext.h" -# endif -# ifndef _ -# define _(msgid) gettext (msgid) -# endif - -# ifdef _LIBC -# include -# endif - -# ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) -# define __attribute__(Spec) /* empty */ -# endif -# endif - -static void -__attribute__ ((noreturn)) -print_and_abort (void) -{ - /* Don't change any of these strings. Yes, it would be possible to add - the newline to the string and use fputs or so. But this must not - happen because the "memory exhausted" message appears in other places - like this and the translation should be reused instead of creating - a very similar string which requires a separate translation. */ -# ifdef _LIBC - (void) __fxprintf (NULL, "%s\n", _("memory exhausted")); -# else - fprintf (stderr, "%s\n", _("memory exhausted")); -# endif - exit (obstack_exit_failure); -} - -#endif /* !ELIDE_CODE */ diff --git a/src/bin/m4/lib/obstack.h b/src/bin/m4/lib/obstack.h deleted file mode 100644 index 3315dfe617..0000000000 --- a/src/bin/m4/lib/obstack.h +++ /dev/null @@ -1,513 +0,0 @@ -/* obstack.h - object stack macros - Copyright (C) 1988-1994,1996-1999,2003,2004,2005,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Summary: - -All the apparent functions defined here are macros. The idea -is that you would use these pre-tested macros to solve a -very specific set of problems, and they would run fast. -Caution: no side-effects in arguments please!! They may be -evaluated MANY times!! - -These macros operate a stack of objects. Each object starts life -small, and may grow to maturity. (Consider building a word syllable -by syllable.) An object can move while it is growing. Once it has -been "finished" it never changes address again. So the "top of the -stack" is typically an immature growing object, while the rest of the -stack is of mature, fixed size and fixed address objects. - -These routines grab large chunks of memory, using a function you -supply, called `obstack_chunk_alloc'. On occasion, they free chunks, -by calling `obstack_chunk_free'. You must define them and declare -them before using any obstack macros. - -Each independent stack is represented by a `struct obstack'. -Each of the obstack macros expects a pointer to such a structure -as the first argument. - -One motivation for this package is the problem of growing char strings -in symbol tables. Unless you are "fascist pig with a read-only mind" ---Gosper's immortal quote from HAKMEM item 154, out of context--you -would not like to put any arbitrary upper limit on the length of your -symbols. - -In practice this often means you will build many short symbols and a -few long symbols. At the time you are reading a symbol you don't know -how long it is. One traditional method is to read a symbol into a -buffer, realloc()ating the buffer every time you try to read a symbol -that is longer than the buffer. This is beaut, but you still will -want to copy the symbol from the buffer to a more permanent -symbol-table entry say about half the time. - -With obstacks, you can work differently. Use one obstack for all symbol -names. As you read a symbol, grow the name in the obstack gradually. -When the name is complete, finalize it. Then, if the symbol exists already, -free the newly read name. - -The way we do this is to take a large chunk, allocating memory from -low addresses. When you want to build a symbol in the chunk you just -add chars above the current "high water mark" in the chunk. When you -have finished adding chars, because you got to the end of the symbol, -you know how long the chars are, and you can create a new object. -Mostly the chars will not burst over the highest address of the chunk, -because you would typically expect a chunk to be (say) 100 times as -long as an average object. - -In case that isn't clear, when we have enough chars to make up -the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) -so we just point to it where it lies. No moving of chars is -needed and this is the second win: potentially long strings need -never be explicitly shuffled. Once an object is formed, it does not -change its address during its lifetime. - -When the chars burst over a chunk boundary, we allocate a larger -chunk, and then copy the partly formed object from the end of the old -chunk to the beginning of the new larger chunk. We then carry on -accreting characters to the end of the object as we normally would. - -A special macro is provided to add a single char at a time to a -growing object. This allows the use of register variables, which -break the ordinary 'growth' macro. - -Summary: - We allocate large chunks. - We carve out one object at a time from the current chunk. - Once carved, an object never moves. - We are free to append data of any size to the currently - growing object. - Exactly one object is growing in an obstack at any one time. - You can run one obstack per control block. - You may have as many control blocks as you dare. - Because of the way we do it, you can `unwind' an obstack - back to a previous state. (You may remove objects much - as you would with a stack.) -*/ - - -/* Don't do the contents of this file more than once. */ - -#ifndef _OBSTACK_H -#define _OBSTACK_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is - defined, as with GNU C, use that; that way we don't pollute the - namespace with 's symbols. Otherwise, include - and use ptrdiff_t. */ - -#ifdef __PTRDIFF_TYPE__ -# define PTR_INT_TYPE __PTRDIFF_TYPE__ -#else -# include -# define PTR_INT_TYPE ptrdiff_t -#endif - -/* If B is the base of an object addressed by P, return the result of - aligning P to the next multiple of A + 1. B and P must be of type - char *. A + 1 must be a power of 2. */ - -#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) - -/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case - where pointers can be converted to integers, aligned as integers, - and converted back again. If PTR_INT_TYPE is narrower than a - pointer (e.g., the AS/400), play it safe and compute the alignment - relative to B. Otherwise, use the faster strategy of computing the - alignment relative to 0. */ - -#define __PTR_ALIGN(B, P, A) \ - __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ - P, A) - -#include - -struct _obstack_chunk /* Lives at front of each chunk. */ -{ - char *limit; /* 1 past end of this chunk */ - struct _obstack_chunk *prev; /* address of prior chunk or NULL */ - char contents[4]; /* objects begin here */ -}; - -struct obstack /* control current object in current chunk */ -{ - long chunk_size; /* preferred size to allocate chunks in */ - struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ - char *object_base; /* address of object we are building */ - char *next_free; /* where to add next char to current object */ - char *chunk_limit; /* address of char after current chunk */ - union - { - PTR_INT_TYPE tempint; - void *tempptr; - } temp; /* Temporary for some macros. */ - int alignment_mask; /* Mask of alignment for each object. */ - /* These prototypes vary based on `use_extra_arg', and we use - casts to the prototypeless function type in all assignments, - but having prototypes here quiets -Wstrict-prototypes. */ - struct _obstack_chunk *(*chunkfun) (void *, long); - void (*freefun) (void *, struct _obstack_chunk *); - void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ - unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ - unsigned maybe_empty_object:1;/* There is a possibility that the current - chunk contains a zero-length object. This - prevents freeing the chunk if we allocate - a bigger chunk to replace it. */ - unsigned alloc_failed:1; /* No longer used, as we now call the failed - handler on error, but retained for binary - compatibility. */ -}; - -/* Declare the external functions we use; they are in obstack.c. */ - -extern void _obstack_newchunk (struct obstack *, int); -extern int _obstack_begin (struct obstack *, int, int, - void *(*) (long), void (*) (void *)); -extern int _obstack_begin_1 (struct obstack *, int, int, - void *(*) (void *, long), - void (*) (void *, void *), void *); -extern int _obstack_memory_used (struct obstack *); - -/* The default name of the function for freeing a chunk is 'obstack_free', - but gnulib users can override this by defining '__obstack_free'. */ -#ifndef __obstack_free -# define __obstack_free obstack_free -#endif -extern void __obstack_free (struct obstack *obstack, void *block); - - -/* Error handler called when `obstack_chunk_alloc' failed to allocate - more memory. This can be set to a user defined function which - should either abort gracefully or use longjump - but shouldn't - return. The default action is to print a message and abort. */ -extern void (*obstack_alloc_failed_handler) (void); - -/* Exit value used when `print_and_abort' is used. */ -extern int obstack_exit_failure; - -/* Pointer to beginning of object being allocated or to be allocated next. - Note that this might not be the final address of the object - because a new chunk might be needed to hold the final size. */ - -#define obstack_base(h) ((void *) (h)->object_base) - -/* Size for allocating ordinary chunks. */ - -#define obstack_chunk_size(h) ((h)->chunk_size) - -/* Pointer to next byte not yet allocated in current chunk. */ - -#define obstack_next_free(h) ((h)->next_free) - -/* Mask specifying low bits that should be clear in address of an object. */ - -#define obstack_alignment_mask(h) ((h)->alignment_mask) - -/* To prevent prototype warnings provide complete argument list. */ -#define obstack_init(h) \ - _obstack_begin ((h), 0, 0, \ - (void *(*) (long)) obstack_chunk_alloc, \ - (void (*) (void *)) obstack_chunk_free) - -#define obstack_begin(h, size) \ - _obstack_begin ((h), (size), 0, \ - (void *(*) (long)) obstack_chunk_alloc, \ - (void (*) (void *)) obstack_chunk_free) - -#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ - _obstack_begin ((h), (size), (alignment), \ - (void *(*) (long)) (chunkfun), \ - (void (*) (void *)) (freefun)) - -#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ - _obstack_begin_1 ((h), (size), (alignment), \ - (void *(*) (void *, long)) (chunkfun), \ - (void (*) (void *, void *)) (freefun), (arg)) - -#define obstack_chunkfun(h, newchunkfun) \ - ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) - -#define obstack_freefun(h, newfreefun) \ - ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) - -#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) - -#define obstack_blank_fast(h,n) ((h)->next_free += (n)) - -#define obstack_memory_used(h) _obstack_memory_used (h) - -#if defined __GNUC__ && defined __STDC__ && __STDC__ -/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and - does not implement __extension__. But that compiler doesn't define - __GNUC_MINOR__. */ -# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) -# define __extension__ -# endif - -/* For GNU C, if not -traditional, - we can define these macros to compute all args only once - without using a global variable. - Also, we can avoid using the `temp' slot, to make faster code. */ - -# define obstack_object_size(OBSTACK) \ - __extension__ \ - ({ struct obstack const *__o = (OBSTACK); \ - (unsigned) (__o->next_free - __o->object_base); }) - -# define obstack_room(OBSTACK) \ - __extension__ \ - ({ struct obstack const *__o = (OBSTACK); \ - (unsigned) (__o->chunk_limit - __o->next_free); }) - -# define obstack_make_room(OBSTACK,length) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->chunk_limit - __o->next_free < __len) \ - _obstack_newchunk (__o, __len); \ - (void) 0; }) - -# define obstack_empty_p(OBSTACK) \ - __extension__ \ - ({ struct obstack const *__o = (OBSTACK); \ - (__o->chunk->prev == 0 \ - && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ - __o->chunk->contents, \ - __o->alignment_mask)); }) - -# define obstack_grow(OBSTACK,where,length) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->next_free + __len > __o->chunk_limit) \ - _obstack_newchunk (__o, __len); \ - memcpy (__o->next_free, where, __len); \ - __o->next_free += __len; \ - (void) 0; }) - -# define obstack_grow0(OBSTACK,where,length) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->next_free + __len + 1 > __o->chunk_limit) \ - _obstack_newchunk (__o, __len + 1); \ - memcpy (__o->next_free, where, __len); \ - __o->next_free += __len; \ - *(__o->next_free)++ = 0; \ - (void) 0; }) - -# define obstack_1grow(OBSTACK,datum) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - if (__o->next_free + 1 > __o->chunk_limit) \ - _obstack_newchunk (__o, 1); \ - obstack_1grow_fast (__o, datum); \ - (void) 0; }) - -/* These assume that the obstack alignment is good enough for pointers - or ints, and that the data added so far to the current object - shares that much alignment. */ - -# define obstack_ptr_grow(OBSTACK,datum) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ - _obstack_newchunk (__o, sizeof (void *)); \ - obstack_ptr_grow_fast (__o, datum); }) \ - -# define obstack_int_grow(OBSTACK,datum) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - if (__o->next_free + sizeof (int) > __o->chunk_limit) \ - _obstack_newchunk (__o, sizeof (int)); \ - obstack_int_grow_fast (__o, datum); }) - -# define obstack_ptr_grow_fast(OBSTACK,aptr) \ -__extension__ \ -({ struct obstack *__o1 = (OBSTACK); \ - *(const void **) __o1->next_free = (aptr); \ - __o1->next_free += sizeof (const void *); \ - (void) 0; }) - -# define obstack_int_grow_fast(OBSTACK,aint) \ -__extension__ \ -({ struct obstack *__o1 = (OBSTACK); \ - *(int *) __o1->next_free = (aint); \ - __o1->next_free += sizeof (int); \ - (void) 0; }) - -# define obstack_blank(OBSTACK,length) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->chunk_limit - __o->next_free < __len) \ - _obstack_newchunk (__o, __len); \ - obstack_blank_fast (__o, __len); \ - (void) 0; }) - -# define obstack_alloc(OBSTACK,length) \ -__extension__ \ -({ struct obstack *__h = (OBSTACK); \ - obstack_blank (__h, (length)); \ - obstack_finish (__h); }) - -# define obstack_copy(OBSTACK,where,length) \ -__extension__ \ -({ struct obstack *__h = (OBSTACK); \ - obstack_grow (__h, (where), (length)); \ - obstack_finish (__h); }) - -# define obstack_copy0(OBSTACK,where,length) \ -__extension__ \ -({ struct obstack *__h = (OBSTACK); \ - obstack_grow0 (__h, (where), (length)); \ - obstack_finish (__h); }) - -/* The local variable is named __o1 to avoid a name conflict - when obstack_blank is called. */ -# define obstack_finish(OBSTACK) \ -__extension__ \ -({ struct obstack *__o1 = (OBSTACK); \ - void *__value = (void *) __o1->object_base; \ - if (__o1->next_free == __value) \ - __o1->maybe_empty_object = 1; \ - __o1->next_free \ - = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ - __o1->alignment_mask); \ - if (__o1->next_free - (char *)__o1->chunk \ - > __o1->chunk_limit - (char *)__o1->chunk) \ - __o1->next_free = __o1->chunk_limit; \ - __o1->object_base = __o1->next_free; \ - __value; }) - -# define obstack_free(OBSTACK, OBJ) \ -__extension__ \ -({ struct obstack *__o = (OBSTACK); \ - void *__obj = (OBJ); \ - if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ - __o->next_free = __o->object_base = (char *)__obj; \ - else (__obstack_free) (__o, __obj); }) - -#else /* not __GNUC__ or not __STDC__ */ - -# define obstack_object_size(h) \ - (unsigned) ((h)->next_free - (h)->object_base) - -# define obstack_room(h) \ - (unsigned) ((h)->chunk_limit - (h)->next_free) - -# define obstack_empty_p(h) \ - ((h)->chunk->prev == 0 \ - && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ - (h)->chunk->contents, \ - (h)->alignment_mask)) - -/* Note that the call to _obstack_newchunk is enclosed in (..., 0) - so that we can avoid having void expressions - in the arms of the conditional expression. - Casting the third operand to void was tried before, - but some compilers won't accept it. */ - -# define obstack_make_room(h,length) \ -( (h)->temp.tempint = (length), \ - (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) - -# define obstack_grow(h,where,length) \ -( (h)->temp.tempint = (length), \ - (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ - memcpy ((h)->next_free, where, (h)->temp.tempint), \ - (h)->next_free += (h)->temp.tempint) - -# define obstack_grow0(h,where,length) \ -( (h)->temp.tempint = (length), \ - (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ - memcpy ((h)->next_free, where, (h)->temp.tempint), \ - (h)->next_free += (h)->temp.tempint, \ - *((h)->next_free)++ = 0) - -# define obstack_1grow(h,datum) \ -( (((h)->next_free + 1 > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), 1), 0) : 0), \ - obstack_1grow_fast (h, datum)) - -# define obstack_ptr_grow(h,datum) \ -( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ - obstack_ptr_grow_fast (h, datum)) - -# define obstack_int_grow(h,datum) \ -( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ - ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ - obstack_int_grow_fast (h, datum)) - -# define obstack_ptr_grow_fast(h,aptr) \ - (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) - -# define obstack_int_grow_fast(h,aint) \ - (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) - -# define obstack_blank(h,length) \ -( (h)->temp.tempint = (length), \ - (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ - ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ - obstack_blank_fast (h, (h)->temp.tempint)) - -# define obstack_alloc(h,length) \ - (obstack_blank ((h), (length)), obstack_finish ((h))) - -# define obstack_copy(h,where,length) \ - (obstack_grow ((h), (where), (length)), obstack_finish ((h))) - -# define obstack_copy0(h,where,length) \ - (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) - -# define obstack_finish(h) \ -( ((h)->next_free == (h)->object_base \ - ? (((h)->maybe_empty_object = 1), 0) \ - : 0), \ - (h)->temp.tempptr = (h)->object_base, \ - (h)->next_free \ - = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ - (h)->alignment_mask), \ - (((h)->next_free - (char *) (h)->chunk \ - > (h)->chunk_limit - (char *) (h)->chunk) \ - ? ((h)->next_free = (h)->chunk_limit) : 0), \ - (h)->object_base = (h)->next_free, \ - (h)->temp.tempptr) - -# define obstack_free(h,obj) \ -( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ - ((((h)->temp.tempint > 0 \ - && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ - ? (int) ((h)->next_free = (h)->object_base \ - = (h)->temp.tempint + (char *) (h)->chunk) \ - : (((__obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) - -#endif /* not __GNUC__ or not __STDC__ */ - -#ifdef __cplusplus -} /* C++ */ -#endif - -#endif /* obstack.h */ diff --git a/src/bin/m4/lib/pathmax.h b/src/bin/m4/lib/pathmax.h deleted file mode 100644 index 6941e457e3..0000000000 --- a/src/bin/m4/lib/pathmax.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Define PATH_MAX somehow. Requires sys/types.h. - Copyright (C) 1992, 1999, 2001, 2003, 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _PATHMAX_H -# define _PATHMAX_H - -# include - -# include - -# ifndef _POSIX_PATH_MAX -# define _POSIX_PATH_MAX 256 -# endif - -# if !defined PATH_MAX && defined _PC_PATH_MAX -# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 \ - : pathconf ("/", _PC_PATH_MAX)) -# endif - -/* Don't include sys/param.h if it already has been. */ -# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN -# include -# endif - -# if !defined PATH_MAX && defined MAXPATHLEN -# define PATH_MAX MAXPATHLEN -# endif - -# ifndef PATH_MAX -# define PATH_MAX _POSIX_PATH_MAX -# endif - -#endif /* _PATHMAX_H */ diff --git a/src/bin/m4/lib/pipe-safer.c b/src/bin/m4/lib/pipe-safer.c deleted file mode 100644 index e4431b33a4..0000000000 --- a/src/bin/m4/lib/pipe-safer.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Invoke pipe, but avoid some glitches. - Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#include - -#include "unistd-safer.h" - -#include -#include - -/* Like pipe, but ensure that neither of the file descriptors is - STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. Fail with ENOSYS on - platforms that lack pipe. */ - -int -pipe_safer (int fd[2]) -{ -#if HAVE_PIPE - if (pipe (fd) == 0) - { - int i; - for (i = 0; i < 2; i++) - { - fd[i] = fd_safer (fd[i]); - if (fd[i] < 0) - { - int e = errno; - close (fd[1 - i]); - errno = e; - return -1; - } - } - - return 0; - } -#else - errno = ENOSYS; -#endif - - return -1; -} diff --git a/src/bin/m4/lib/printf-args.c b/src/bin/m4/lib/printf-args.c deleted file mode 100644 index 358801c97b..0000000000 --- a/src/bin/m4/lib/printf-args.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Decomposed printf argument list. - Copyright (C) 1999, 2002-2003, 2005-2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "printf-args.h" - -#ifdef STATIC -STATIC -#endif -int -printf_fetchargs (va_list args, arguments *a) -{ - size_t i; - argument *ap; - - for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) - switch (ap->type) - { - case TYPE_SCHAR: - ap->a.a_schar = va_arg (args, /*signed char*/ int); - break; - case TYPE_UCHAR: - ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); - break; - case TYPE_SHORT: - ap->a.a_short = va_arg (args, /*short*/ int); - break; - case TYPE_USHORT: - ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); - break; - case TYPE_INT: - ap->a.a_int = va_arg (args, int); - break; - case TYPE_UINT: - ap->a.a_uint = va_arg (args, unsigned int); - break; - case TYPE_LONGINT: - ap->a.a_longint = va_arg (args, long int); - break; - case TYPE_ULONGINT: - ap->a.a_ulongint = va_arg (args, unsigned long int); - break; -#ifdef HAVE_LONG_LONG_INT - case TYPE_LONGLONGINT: - ap->a.a_longlongint = va_arg (args, long long int); - break; - case TYPE_ULONGLONGINT: - ap->a.a_ulonglongint = va_arg (args, unsigned long long int); - break; -#endif - case TYPE_DOUBLE: - ap->a.a_double = va_arg (args, double); - break; -#ifdef HAVE_LONG_DOUBLE - case TYPE_LONGDOUBLE: - ap->a.a_longdouble = va_arg (args, long double); - break; -#endif - case TYPE_CHAR: - ap->a.a_char = va_arg (args, int); - break; -#ifdef HAVE_WINT_T - case TYPE_WIDE_CHAR: - /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by - default argument promotions", this is not the case in mingw32, - where wint_t is 'unsigned short'. */ - ap->a.a_wide_char = - (sizeof (wint_t) < sizeof (int) - ? va_arg (args, int) - : va_arg (args, wint_t)); - break; -#endif - case TYPE_STRING: - ap->a.a_string = va_arg (args, const char *); - /* A null pointer is an invalid argument for "%s", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_string == NULL) - ap->a.a_string = "(NULL)"; - break; -#ifdef HAVE_WCHAR_T - case TYPE_WIDE_STRING: - ap->a.a_wide_string = va_arg (args, const wchar_t *); - /* A null pointer is an invalid argument for "%ls", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_wide_string == NULL) - { - static const wchar_t wide_null_string[] = - { - (wchar_t)'(', - (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L', - (wchar_t)')', - (wchar_t)0 - }; - ap->a.a_wide_string = wide_null_string; - } - break; -#endif - case TYPE_POINTER: - ap->a.a_pointer = va_arg (args, void *); - break; - case TYPE_COUNT_SCHAR_POINTER: - ap->a.a_count_schar_pointer = va_arg (args, signed char *); - break; - case TYPE_COUNT_SHORT_POINTER: - ap->a.a_count_short_pointer = va_arg (args, short *); - break; - case TYPE_COUNT_INT_POINTER: - ap->a.a_count_int_pointer = va_arg (args, int *); - break; - case TYPE_COUNT_LONGINT_POINTER: - ap->a.a_count_longint_pointer = va_arg (args, long int *); - break; -#ifdef HAVE_LONG_LONG_INT - case TYPE_COUNT_LONGLONGINT_POINTER: - ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); - break; -#endif - default: - /* Unknown type. */ - return -1; - } - return 0; -} diff --git a/src/bin/m4/lib/printf-args.h b/src/bin/m4/lib/printf-args.h deleted file mode 100644 index 5759da0ee9..0000000000 --- a/src/bin/m4/lib/printf-args.h +++ /dev/null @@ -1,136 +0,0 @@ -/* Decomposed printf argument list. - Copyright (C) 1999, 2002-2003, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _PRINTF_ARGS_H -#define _PRINTF_ARGS_H - -/* Get size_t. */ -#include - -/* Get wchar_t. */ -#ifdef HAVE_WCHAR_T -# include -#endif - -/* Get wint_t. */ -#ifdef HAVE_WINT_T -# include -#endif - -/* Get va_list. */ -#include - - -/* Argument types */ -typedef enum -{ - TYPE_NONE, - TYPE_SCHAR, - TYPE_UCHAR, - TYPE_SHORT, - TYPE_USHORT, - TYPE_INT, - TYPE_UINT, - TYPE_LONGINT, - TYPE_ULONGINT, -#ifdef HAVE_LONG_LONG_INT - TYPE_LONGLONGINT, - TYPE_ULONGLONGINT, -#endif - TYPE_DOUBLE, -#ifdef HAVE_LONG_DOUBLE - TYPE_LONGDOUBLE, -#endif - TYPE_CHAR, -#ifdef HAVE_WINT_T - TYPE_WIDE_CHAR, -#endif - TYPE_STRING, -#ifdef HAVE_WCHAR_T - TYPE_WIDE_STRING, -#endif - TYPE_POINTER, - TYPE_COUNT_SCHAR_POINTER, - TYPE_COUNT_SHORT_POINTER, - TYPE_COUNT_INT_POINTER, - TYPE_COUNT_LONGINT_POINTER -#ifdef HAVE_LONG_LONG_INT -, TYPE_COUNT_LONGLONGINT_POINTER -#endif -} arg_type; - -/* Polymorphic argument */ -typedef struct -{ - arg_type type; - union - { - signed char a_schar; - unsigned char a_uchar; - short a_short; - unsigned short a_ushort; - int a_int; - unsigned int a_uint; - long int a_longint; - unsigned long int a_ulongint; -#ifdef HAVE_LONG_LONG_INT - long long int a_longlongint; - unsigned long long int a_ulonglongint; -#endif - float a_float; - double a_double; -#ifdef HAVE_LONG_DOUBLE - long double a_longdouble; -#endif - int a_char; -#ifdef HAVE_WINT_T - wint_t a_wide_char; -#endif - const char* a_string; -#ifdef HAVE_WCHAR_T - const wchar_t* a_wide_string; -#endif - void* a_pointer; - signed char * a_count_schar_pointer; - short * a_count_short_pointer; - int * a_count_int_pointer; - long int * a_count_longint_pointer; -#ifdef HAVE_LONG_LONG_INT - long long int * a_count_longlongint_pointer; -#endif - } - a; -} -argument; - -typedef struct -{ - size_t count; - argument *arg; -} -arguments; - - -/* Fetch the arguments, putting them into a. */ -#ifdef STATIC -STATIC -#else -extern -#endif -int printf_fetchargs (va_list args, arguments *a); - -#endif /* _PRINTF_ARGS_H */ diff --git a/src/bin/m4/lib/printf-parse.c b/src/bin/m4/lib/printf-parse.c deleted file mode 100644 index 9a86f7738e..0000000000 --- a/src/bin/m4/lib/printf-parse.c +++ /dev/null @@ -1,543 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 1999-2000, 2002-2003, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#if WIDE_CHAR_VERSION -# include "wprintf-parse.h" -#else -# include "printf-parse.h" -#endif - -/* Get size_t, NULL. */ -#include - -/* Get intmax_t. */ -#if HAVE_STDINT_H_WITH_UINTMAX -# include -#endif -#if HAVE_INTTYPES_H_WITH_UINTMAX -# include -#endif - -/* malloc(), realloc(), free(). */ -#include - -/* Checked size_t computations. */ -#include "xsize.h" - -#if WIDE_CHAR_VERSION -# define PRINTF_PARSE wprintf_parse -# define CHAR_T wchar_t -# define DIRECTIVE wchar_t_directive -# define DIRECTIVES wchar_t_directives -#else -# define PRINTF_PARSE printf_parse -# define CHAR_T char -# define DIRECTIVE char_directive -# define DIRECTIVES char_directives -#endif - -#ifdef STATIC -STATIC -#endif -int -PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) -{ - const CHAR_T *cp = format; /* pointer into format */ - size_t arg_posn = 0; /* number of regular arguments consumed */ - size_t d_allocated; /* allocated elements of d->dir */ - size_t a_allocated; /* allocated elements of a->arg */ - size_t max_width_length = 0; - size_t max_precision_length = 0; - - d->count = 0; - d_allocated = 1; - d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE)); - if (d->dir == NULL) - /* Out of memory. */ - return -1; - - a->count = 0; - a_allocated = 0; - a->arg = NULL; - -#define REGISTER_ARG(_index_,_type_) \ - { \ - size_t n = (_index_); \ - if (n >= a_allocated) \ - { \ - size_t memory_size; \ - argument *memory; \ - \ - a_allocated = xtimes (a_allocated, 2); \ - if (a_allocated <= n) \ - a_allocated = xsum (n, 1); \ - memory_size = xtimes (a_allocated, sizeof (argument)); \ - if (size_overflow_p (memory_size)) \ - /* Overflow, would lead to out of memory. */ \ - goto error; \ - memory = (argument *) (a->arg \ - ? realloc (a->arg, memory_size) \ - : malloc (memory_size)); \ - if (memory == NULL) \ - /* Out of memory. */ \ - goto error; \ - a->arg = memory; \ - } \ - while (a->count <= n) \ - a->arg[a->count++].type = TYPE_NONE; \ - if (a->arg[n].type == TYPE_NONE) \ - a->arg[n].type = (_type_); \ - else if (a->arg[n].type != (_type_)) \ - /* Ambiguous type for positional argument. */ \ - goto error; \ - } - - while (*cp != '\0') - { - CHAR_T c = *cp++; - if (c == '%') - { - size_t arg_index = ARG_NONE; - DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ - - /* Initialize the next directive. */ - dp->dir_start = cp - 1; - dp->flags = 0; - dp->width_start = NULL; - dp->width_end = NULL; - dp->width_arg_index = ARG_NONE; - dp->precision_start = NULL; - dp->precision_end = NULL; - dp->precision_arg_index = ARG_NONE; - dp->arg_index = ARG_NONE; - - /* Test for positional argument. */ - if (*cp >= '0' && *cp <= '9') - { - const CHAR_T *np; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - ; - if (*np == '$') - { - size_t n = 0; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - n = xsum (xtimes (n, 10), *np - '0'); - if (n == 0) - /* Positional argument 0. */ - goto error; - if (size_overflow_p (n)) - /* n too large, would lead to out of memory later. */ - goto error; - arg_index = n - 1; - cp = np + 1; - } - } - - /* Read the flags. */ - for (;;) - { - if (*cp == '\'') - { - dp->flags |= FLAG_GROUP; - cp++; - } - else if (*cp == '-') - { - dp->flags |= FLAG_LEFT; - cp++; - } - else if (*cp == '+') - { - dp->flags |= FLAG_SHOWSIGN; - cp++; - } - else if (*cp == ' ') - { - dp->flags |= FLAG_SPACE; - cp++; - } - else if (*cp == '#') - { - dp->flags |= FLAG_ALT; - cp++; - } - else if (*cp == '0') - { - dp->flags |= FLAG_ZERO; - cp++; - } - else - break; - } - - /* Parse the field width. */ - if (*cp == '*') - { - dp->width_start = cp; - cp++; - dp->width_end = cp; - if (max_width_length < 1) - max_width_length = 1; - - /* Test for positional argument. */ - if (*cp >= '0' && *cp <= '9') - { - const CHAR_T *np; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - ; - if (*np == '$') - { - size_t n = 0; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - n = xsum (xtimes (n, 10), *np - '0'); - if (n == 0) - /* Positional argument 0. */ - goto error; - if (size_overflow_p (n)) - /* n too large, would lead to out of memory later. */ - goto error; - dp->width_arg_index = n - 1; - cp = np + 1; - } - } - if (dp->width_arg_index == ARG_NONE) - { - dp->width_arg_index = arg_posn++; - if (dp->width_arg_index == ARG_NONE) - /* arg_posn wrapped around. */ - goto error; - } - REGISTER_ARG (dp->width_arg_index, TYPE_INT); - } - else if (*cp >= '0' && *cp <= '9') - { - size_t width_length; - - dp->width_start = cp; - for (; *cp >= '0' && *cp <= '9'; cp++) - ; - dp->width_end = cp; - width_length = dp->width_end - dp->width_start; - if (max_width_length < width_length) - max_width_length = width_length; - } - - /* Parse the precision. */ - if (*cp == '.') - { - cp++; - if (*cp == '*') - { - dp->precision_start = cp - 1; - cp++; - dp->precision_end = cp; - if (max_precision_length < 2) - max_precision_length = 2; - - /* Test for positional argument. */ - if (*cp >= '0' && *cp <= '9') - { - const CHAR_T *np; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - ; - if (*np == '$') - { - size_t n = 0; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - n = xsum (xtimes (n, 10), *np - '0'); - if (n == 0) - /* Positional argument 0. */ - goto error; - if (size_overflow_p (n)) - /* n too large, would lead to out of memory - later. */ - goto error; - dp->precision_arg_index = n - 1; - cp = np + 1; - } - } - if (dp->precision_arg_index == ARG_NONE) - { - dp->precision_arg_index = arg_posn++; - if (dp->precision_arg_index == ARG_NONE) - /* arg_posn wrapped around. */ - goto error; - } - REGISTER_ARG (dp->precision_arg_index, TYPE_INT); - } - else - { - size_t precision_length; - - dp->precision_start = cp - 1; - for (; *cp >= '0' && *cp <= '9'; cp++) - ; - dp->precision_end = cp; - precision_length = dp->precision_end - dp->precision_start; - if (max_precision_length < precision_length) - max_precision_length = precision_length; - } - } - - { - arg_type type; - - /* Parse argument type/size specifiers. */ - { - int flags = 0; - - for (;;) - { - if (*cp == 'h') - { - flags |= (1 << (flags & 1)); - cp++; - } - else if (*cp == 'L') - { - flags |= 4; - cp++; - } - else if (*cp == 'l') - { - flags += 8; - cp++; - } -#ifdef HAVE_INTMAX_T - else if (*cp == 'j') - { - if (sizeof (intmax_t) > sizeof (long)) - { - /* intmax_t = long long */ - flags += 16; - } - else if (sizeof (intmax_t) > sizeof (int)) - { - /* intmax_t = long */ - flags += 8; - } - cp++; - } -#endif - else if (*cp == 'z' || *cp == 'Z') - { - /* 'z' is standardized in ISO C 99, but glibc uses 'Z' - because the warning facility in gcc-2.95.2 understands - only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ - if (sizeof (size_t) > sizeof (long)) - { - /* size_t = long long */ - flags += 16; - } - else if (sizeof (size_t) > sizeof (int)) - { - /* size_t = long */ - flags += 8; - } - cp++; - } - else if (*cp == 't') - { - if (sizeof (ptrdiff_t) > sizeof (long)) - { - /* ptrdiff_t = long long */ - flags += 16; - } - else if (sizeof (ptrdiff_t) > sizeof (int)) - { - /* ptrdiff_t = long */ - flags += 8; - } - cp++; - } - else - break; - } - - /* Read the conversion character. */ - c = *cp++; - switch (c) - { - case 'd': case 'i': -#ifdef HAVE_LONG_LONG_INT - /* If 'long long' exists and is larger than 'long': */ - if (flags >= 16 || (flags & 4)) - type = TYPE_LONGLONGINT; - else -#endif - /* If 'long long' exists and is the same as 'long', we parse - "lld" into TYPE_LONGINT. */ - if (flags >= 8) - type = TYPE_LONGINT; - else if (flags & 2) - type = TYPE_SCHAR; - else if (flags & 1) - type = TYPE_SHORT; - else - type = TYPE_INT; - break; - case 'o': case 'u': case 'x': case 'X': -#ifdef HAVE_LONG_LONG_INT - /* If 'long long' exists and is larger than 'long': */ - if (flags >= 16 || (flags & 4)) - type = TYPE_ULONGLONGINT; - else -#endif - /* If 'unsigned long long' exists and is the same as - 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ - if (flags >= 8) - type = TYPE_ULONGINT; - else if (flags & 2) - type = TYPE_UCHAR; - else if (flags & 1) - type = TYPE_USHORT; - else - type = TYPE_UINT; - break; - case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': -#ifdef HAVE_LONG_DOUBLE - if (flags >= 16 || (flags & 4)) - type = TYPE_LONGDOUBLE; - else -#endif - type = TYPE_DOUBLE; - break; - case 'c': - if (flags >= 8) -#ifdef HAVE_WINT_T - type = TYPE_WIDE_CHAR; -#else - goto error; -#endif - else - type = TYPE_CHAR; - break; -#ifdef HAVE_WINT_T - case 'C': - type = TYPE_WIDE_CHAR; - c = 'c'; - break; -#endif - case 's': - if (flags >= 8) -#ifdef HAVE_WCHAR_T - type = TYPE_WIDE_STRING; -#else - goto error; -#endif - else - type = TYPE_STRING; - break; -#ifdef HAVE_WCHAR_T - case 'S': - type = TYPE_WIDE_STRING; - c = 's'; - break; -#endif - case 'p': - type = TYPE_POINTER; - break; - case 'n': -#ifdef HAVE_LONG_LONG_INT - /* If 'long long' exists and is larger than 'long': */ - if (flags >= 16 || (flags & 4)) - type = TYPE_COUNT_LONGLONGINT_POINTER; - else -#endif - /* If 'long long' exists and is the same as 'long', we parse - "lln" into TYPE_COUNT_LONGINT_POINTER. */ - if (flags >= 8) - type = TYPE_COUNT_LONGINT_POINTER; - else if (flags & 2) - type = TYPE_COUNT_SCHAR_POINTER; - else if (flags & 1) - type = TYPE_COUNT_SHORT_POINTER; - else - type = TYPE_COUNT_INT_POINTER; - break; - case '%': - type = TYPE_NONE; - break; - default: - /* Unknown conversion character. */ - goto error; - } - } - - if (type != TYPE_NONE) - { - dp->arg_index = arg_index; - if (dp->arg_index == ARG_NONE) - { - dp->arg_index = arg_posn++; - if (dp->arg_index == ARG_NONE) - /* arg_posn wrapped around. */ - goto error; - } - REGISTER_ARG (dp->arg_index, type); - } - dp->conversion = c; - dp->dir_end = cp; - } - - d->count++; - if (d->count >= d_allocated) - { - size_t memory_size; - DIRECTIVE *memory; - - d_allocated = xtimes (d_allocated, 2); - memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); - if (size_overflow_p (memory_size)) - /* Overflow, would lead to out of memory. */ - goto error; - memory = (DIRECTIVE *) realloc (d->dir, memory_size); - if (memory == NULL) - /* Out of memory. */ - goto error; - d->dir = memory; - } - } - } - d->dir[d->count].dir_start = cp; - - d->max_width_length = max_width_length; - d->max_precision_length = max_precision_length; - return 0; - -error: - if (a->arg) - free (a->arg); - if (d->dir) - free (d->dir); - return -1; -} - -#undef DIRECTIVES -#undef DIRECTIVE -#undef CHAR_T -#undef PRINTF_PARSE diff --git a/src/bin/m4/lib/printf-parse.h b/src/bin/m4/lib/printf-parse.h deleted file mode 100644 index 82a0d37cd7..0000000000 --- a/src/bin/m4/lib/printf-parse.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Parse printf format string. - Copyright (C) 1999, 2002-2003 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _PRINTF_PARSE_H -#define _PRINTF_PARSE_H - -#include "printf-args.h" - - -/* Flags */ -#define FLAG_GROUP 1 /* ' flag */ -#define FLAG_LEFT 2 /* - flag */ -#define FLAG_SHOWSIGN 4 /* + flag */ -#define FLAG_SPACE 8 /* space flag */ -#define FLAG_ALT 16 /* # flag */ -#define FLAG_ZERO 32 - -/* arg_index value indicating that no argument is consumed. */ -#define ARG_NONE (~(size_t)0) - -/* A parsed directive. */ -typedef struct -{ - const char* dir_start; - const char* dir_end; - int flags; - const char* width_start; - const char* width_end; - size_t width_arg_index; - const char* precision_start; - const char* precision_end; - size_t precision_arg_index; - char conversion; /* d i o u x X f e E g G c s p n U % but not C S */ - size_t arg_index; -} -char_directive; - -/* A parsed format string. */ -typedef struct -{ - size_t count; - char_directive *dir; - size_t max_width_length; - size_t max_precision_length; -} -char_directives; - - -/* Parses the format string. Fills in the number N of directives, and fills - in directives[0], ..., directives[N-1], and sets directives[N].dir_start - to the end of the format string. Also fills in the arg_type fields of the - arguments and the needed count of arguments. */ -#ifdef STATIC -STATIC -#else -extern -#endif -int printf_parse (const char *format, char_directives *d, arguments *a); - -#endif /* _PRINTF_PARSE_H */ diff --git a/src/bin/m4/lib/quotearg.c b/src/bin/m4/lib/quotearg.c deleted file mode 100644 index 6f3ee9e86c..0000000000 --- a/src/bin/m4/lib/quotearg.c +++ /dev/null @@ -1,713 +0,0 @@ -/* quotearg.c - quote arguments for output - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert */ - -#include - -#include "quotearg.h" - -#include "xalloc.h" - -#include -#include -#include -#include -#include -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - -#if HAVE_WCHAR_H - -/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared. */ -# include -# include - -# include -#endif - -#if !HAVE_MBRTOWC -/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the - other macros are defined only for documentation and to satisfy C - syntax. */ -# undef MB_CUR_MAX -# define MB_CUR_MAX 1 -# undef mbstate_t -# define mbstate_t int -# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0) -# define iswprint(wc) isprint ((unsigned char) (wc)) -# undef HAVE_MBSINIT -#endif - -#if !defined mbsinit && !HAVE_MBSINIT -# define mbsinit(ps) 1 -#endif - -#ifndef iswprint -# if HAVE_WCTYPE_H -# include -# endif -# if !defined iswprint && !HAVE_ISWPRINT -# define iswprint(wc) 1 -# endif -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#define INT_BITS (sizeof (int) * CHAR_BIT) - -struct quoting_options -{ - /* Basic quoting style. */ - enum quoting_style style; - - /* Quote the characters indicated by this bit vector even if the - quoting style would not normally require them to be quoted. */ - unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1]; -}; - -/* Names of quoting styles. */ -char const *const quoting_style_args[] = -{ - "literal", - "shell", - "shell-always", - "c", - "escape", - "locale", - "clocale", - 0 -}; - -/* Correspondences to quoting style names. */ -enum quoting_style const quoting_style_vals[] = -{ - literal_quoting_style, - shell_quoting_style, - shell_always_quoting_style, - c_quoting_style, - escape_quoting_style, - locale_quoting_style, - clocale_quoting_style -}; - -/* The default quoting options. */ -static struct quoting_options default_quoting_options; - -/* Allocate a new set of quoting options, with contents initially identical - to O if O is not null, or to the default if O is null. - It is the caller's responsibility to free the result. */ -struct quoting_options * -clone_quoting_options (struct quoting_options *o) -{ - int e = errno; - struct quoting_options *p = xmemdup (o ? o : &default_quoting_options, - sizeof *o); - errno = e; - return p; -} - -/* Get the value of O's quoting style. If O is null, use the default. */ -enum quoting_style -get_quoting_style (struct quoting_options *o) -{ - return (o ? o : &default_quoting_options)->style; -} - -/* In O (or in the default if O is null), - set the value of the quoting style to S. */ -void -set_quoting_style (struct quoting_options *o, enum quoting_style s) -{ - (o ? o : &default_quoting_options)->style = s; -} - -/* In O (or in the default if O is null), - set the value of the quoting options for character C to I. - Return the old value. Currently, the only values defined for I are - 0 (the default) and 1 (which means to quote the character even if - it would not otherwise be quoted). */ -int -set_char_quoting (struct quoting_options *o, char c, int i) -{ - unsigned char uc = c; - unsigned int *p = - (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS; - int shift = uc % INT_BITS; - int r = (*p >> shift) & 1; - *p ^= ((i & 1) ^ r) << shift; - return r; -} - -/* MSGID approximates a quotation mark. Return its translation if it - has one; otherwise, return either it or "\"", depending on S. */ -static char const * -gettext_quote (char const *msgid, enum quoting_style s) -{ - char const *translation = _(msgid); - if (translation == msgid && s == clocale_quoting_style) - translation = "\""; - return translation; -} - -/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of - argument ARG (of size ARGSIZE), using QUOTING_STYLE and the - non-quoting-style part of O to control quoting. - Terminate the output with a null character, and return the written - size of the output, not counting the terminating null. - If BUFFERSIZE is too small to store the output string, return the - value that would have been returned had BUFFERSIZE been large enough. - If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE. - - This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG, - ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting - style specified by O, and O may not be null. */ - -static size_t -quotearg_buffer_restyled (char *buffer, size_t buffersize, - char const *arg, size_t argsize, - enum quoting_style quoting_style, - struct quoting_options const *o) -{ - size_t i; - size_t len = 0; - char const *quote_string = 0; - size_t quote_string_len = 0; - bool backslash_escapes = false; - bool unibyte_locale = MB_CUR_MAX == 1; - -#define STORE(c) \ - do \ - { \ - if (len < buffersize) \ - buffer[len] = (c); \ - len++; \ - } \ - while (0) - - switch (quoting_style) - { - case c_quoting_style: - STORE ('"'); - backslash_escapes = true; - quote_string = "\""; - quote_string_len = 1; - break; - - case escape_quoting_style: - backslash_escapes = true; - break; - - case locale_quoting_style: - case clocale_quoting_style: - { - /* TRANSLATORS: - Get translations for open and closing quotation marks. - - The message catalog should translate "`" to a left - quotation mark suitable for the locale, and similarly for - "'". If the catalog has no translation, - locale_quoting_style quotes `like this', and - clocale_quoting_style quotes "like this". - - For example, an American English Unicode locale should - translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and - should translate "'" to U+201D (RIGHT DOUBLE QUOTATION - MARK). A British English Unicode locale should instead - translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and - U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. - - If you don't know what to put here, please see - - and use glyphs suitable for your language. */ - - char const *left = gettext_quote (N_("`"), quoting_style); - char const *right = gettext_quote (N_("'"), quoting_style); - for (quote_string = left; *quote_string; quote_string++) - STORE (*quote_string); - backslash_escapes = true; - quote_string = right; - quote_string_len = strlen (quote_string); - } - break; - - case shell_always_quoting_style: - STORE ('\''); - quote_string = "'"; - quote_string_len = 1; - break; - - default: - break; - } - - for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++) - { - unsigned char c; - unsigned char esc; - - if (backslash_escapes - && quote_string_len - && i + quote_string_len <= argsize - && memcmp (arg + i, quote_string, quote_string_len) == 0) - STORE ('\\'); - - c = arg[i]; - switch (c) - { - case '\0': - if (backslash_escapes) - { - STORE ('\\'); - STORE ('0'); - STORE ('0'); - c = '0'; - } - break; - - case '?': - switch (quoting_style) - { - case shell_quoting_style: - goto use_shell_always_quoting_style; - - case c_quoting_style: - if (i + 2 < argsize && arg[i + 1] == '?') - switch (arg[i + 2]) - { - case '!': case '\'': - case '(': case ')': case '-': case '/': - case '<': case '=': case '>': - /* Escape the second '?' in what would otherwise be - a trigraph. */ - c = arg[i + 2]; - i += 2; - STORE ('?'); - STORE ('\\'); - STORE ('?'); - break; - - default: - break; - } - break; - - default: - break; - } - break; - - case '\a': esc = 'a'; goto c_escape; - case '\b': esc = 'b'; goto c_escape; - case '\f': esc = 'f'; goto c_escape; - case '\n': esc = 'n'; goto c_and_shell_escape; - case '\r': esc = 'r'; goto c_and_shell_escape; - case '\t': esc = 't'; goto c_and_shell_escape; - case '\v': esc = 'v'; goto c_escape; - case '\\': esc = c; goto c_and_shell_escape; - - c_and_shell_escape: - if (quoting_style == shell_quoting_style) - goto use_shell_always_quoting_style; - c_escape: - if (backslash_escapes) - { - c = esc; - goto store_escape; - } - break; - - case '{': case '}': /* sometimes special if isolated */ - if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1)) - break; - /* Fall through. */ - case '#': case '~': - if (i != 0) - break; - /* Fall through. */ - case ' ': - case '!': /* special in bash */ - case '"': case '$': case '&': - case '(': case ')': case '*': case ';': - case '<': - case '=': /* sometimes special in 0th or (with "set -k") later args */ - case '>': case '[': - case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */ - case '`': case '|': - /* A shell special character. In theory, '$' and '`' could - be the first bytes of multibyte characters, which means - we should check them with mbrtowc, but in practice this - doesn't happen so it's not worth worrying about. */ - if (quoting_style == shell_quoting_style) - goto use_shell_always_quoting_style; - break; - - case '\'': - switch (quoting_style) - { - case shell_quoting_style: - goto use_shell_always_quoting_style; - - case shell_always_quoting_style: - STORE ('\''); - STORE ('\\'); - STORE ('\''); - break; - - default: - break; - } - break; - - case '%': case '+': case ',': case '-': case '.': case '/': - case '0': case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': case ':': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': case ']': case '_': case 'a': case 'b': - case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': - case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': - case 'o': case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - /* These characters don't cause problems, no matter what the - quoting style is. They cannot start multibyte sequences. */ - break; - - default: - /* If we have a multibyte sequence, copy it until we reach - its end, find an error, or come back to the initial shift - state. For C-like styles, if the sequence has - unprintable characters, escape the whole sequence, since - we can't easily escape single characters within it. */ - { - /* Length of multibyte sequence found so far. */ - size_t m; - - bool printable; - - if (unibyte_locale) - { - m = 1; - printable = isprint (c) != 0; - } - else - { - mbstate_t mbstate; - memset (&mbstate, 0, sizeof mbstate); - - m = 0; - printable = true; - if (argsize == SIZE_MAX) - argsize = strlen (arg); - - do - { - wchar_t w; - size_t bytes = mbrtowc (&w, &arg[i + m], - argsize - (i + m), &mbstate); - if (bytes == 0) - break; - else if (bytes == (size_t) -1) - { - printable = false; - break; - } - else if (bytes == (size_t) -2) - { - printable = false; - while (i + m < argsize && arg[i + m]) - m++; - break; - } - else - { - /* Work around a bug with older shells that "see" a '\' - that is really the 2nd byte of a multibyte character. - In practice the problem is limited to ASCII - chars >= '@' that are shell special chars. */ - if ('[' == 0x5b && quoting_style == shell_quoting_style) - { - size_t j; - for (j = 1; j < bytes; j++) - switch (arg[i + m + j]) - { - case '[': case '\\': case '^': - case '`': case '|': - goto use_shell_always_quoting_style; - - default: - break; - } - } - - if (! iswprint (w)) - printable = false; - m += bytes; - } - } - while (! mbsinit (&mbstate)); - } - - if (1 < m || (backslash_escapes && ! printable)) - { - /* Output a multibyte sequence, or an escaped - unprintable unibyte character. */ - size_t ilim = i + m; - - for (;;) - { - if (backslash_escapes && ! printable) - { - STORE ('\\'); - STORE ('0' + (c >> 6)); - STORE ('0' + ((c >> 3) & 7)); - c = '0' + (c & 7); - } - if (ilim <= i + 1) - break; - STORE (c); - c = arg[++i]; - } - - goto store_c; - } - } - } - - if (! (backslash_escapes - && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))) - goto store_c; - - store_escape: - STORE ('\\'); - - store_c: - STORE (c); - } - - if (i == 0 && quoting_style == shell_quoting_style) - goto use_shell_always_quoting_style; - - if (quote_string) - for (; *quote_string; quote_string++) - STORE (*quote_string); - - if (len < buffersize) - buffer[len] = '\0'; - return len; - - use_shell_always_quoting_style: - return quotearg_buffer_restyled (buffer, buffersize, arg, argsize, - shell_always_quoting_style, o); -} - -/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of - argument ARG (of size ARGSIZE), using O to control quoting. - If O is null, use the default. - Terminate the output with a null character, and return the written - size of the output, not counting the terminating null. - If BUFFERSIZE is too small to store the output string, return the - value that would have been returned had BUFFERSIZE been large enough. - If ARGSIZE is SIZE_MAX, use the string length of the argument for - ARGSIZE. */ -size_t -quotearg_buffer (char *buffer, size_t buffersize, - char const *arg, size_t argsize, - struct quoting_options const *o) -{ - struct quoting_options const *p = o ? o : &default_quoting_options; - int e = errno; - size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize, - p->style, p); - errno = e; - return r; -} - -/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly - allocated storage containing the quoted string. */ -char * -quotearg_alloc (char const *arg, size_t argsize, - struct quoting_options const *o) -{ - int e = errno; - size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1; - char *buf = xcharalloc (bufsize); - quotearg_buffer (buf, bufsize, arg, argsize, o); - errno = e; - return buf; -} - -/* A storage slot with size and pointer to a value. */ -struct slotvec -{ - size_t size; - char *val; -}; - -/* Preallocate a slot 0 buffer, so that the caller can always quote - one small component of a "memory exhausted" message in slot 0. */ -static char slot0[256]; -static unsigned int nslots = 1; -static struct slotvec slotvec0 = {sizeof slot0, slot0}; -static struct slotvec *slotvec = &slotvec0; - -void -quotearg_free (void) -{ - struct slotvec *sv = slotvec; - unsigned int i; - for (i = 1; i < nslots; i++) - free (sv[i].val); - if (sv[0].val != slot0) - { - free (sv[0].val); - slotvec0.size = sizeof slot0; - slotvec0.val = slot0; - } - if (sv != &slotvec0) - { - free (sv); - slotvec = &slotvec0; - } - nslots = 1; -} - -/* Use storage slot N to return a quoted version of argument ARG. - ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a - null-terminated string. - OPTIONS specifies the quoting options. - The returned value points to static storage that can be - reused by the next call to this function with the same value of N. - N must be nonnegative. N is deliberately declared with type "int" - to allow for future extensions (using negative values). */ -static char * -quotearg_n_options (int n, char const *arg, size_t argsize, - struct quoting_options const *options) -{ - int e = errno; - - unsigned int n0 = n; - struct slotvec *sv = slotvec; - - if (n < 0) - abort (); - - if (nslots <= n0) - { - /* FIXME: technically, the type of n1 should be `unsigned int', - but that evokes an unsuppressible warning from gcc-4.0.1 and - older. If gcc ever provides an option to suppress that warning, - revert to the original type, so that the test in xalloc_oversized - is once again performed only at compile time. */ - size_t n1 = n0 + 1; - bool preallocated = (sv == &slotvec0); - - if (xalloc_oversized (n1, sizeof *sv)) - xalloc_die (); - - slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv); - if (preallocated) - *sv = slotvec0; - memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv); - nslots = n1; - } - - { - size_t size = sv[n].size; - char *val = sv[n].val; - size_t qsize = quotearg_buffer (val, size, arg, argsize, options); - - if (size <= qsize) - { - sv[n].size = size = qsize + 1; - if (val != slot0) - free (val); - sv[n].val = val = xcharalloc (size); - quotearg_buffer (val, size, arg, argsize, options); - } - - errno = e; - return val; - } -} - -char * -quotearg_n (int n, char const *arg) -{ - return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options); -} - -char * -quotearg (char const *arg) -{ - return quotearg_n (0, arg); -} - -/* Return quoting options for STYLE, with no extra quoting. */ -static struct quoting_options -quoting_options_from_style (enum quoting_style style) -{ - struct quoting_options o; - o.style = style; - memset (o.quote_these_too, 0, sizeof o.quote_these_too); - return o; -} - -char * -quotearg_n_style (int n, enum quoting_style s, char const *arg) -{ - struct quoting_options const o = quoting_options_from_style (s); - return quotearg_n_options (n, arg, SIZE_MAX, &o); -} - -char * -quotearg_n_style_mem (int n, enum quoting_style s, - char const *arg, size_t argsize) -{ - struct quoting_options const o = quoting_options_from_style (s); - return quotearg_n_options (n, arg, argsize, &o); -} - -char * -quotearg_style (enum quoting_style s, char const *arg) -{ - return quotearg_n_style (0, s, arg); -} - -char * -quotearg_char (char const *arg, char ch) -{ - struct quoting_options options; - options = default_quoting_options; - set_char_quoting (&options, ch, 1); - return quotearg_n_options (0, arg, SIZE_MAX, &options); -} - -char * -quotearg_colon (char const *arg) -{ - return quotearg_char (arg, ':'); -} diff --git a/src/bin/m4/lib/quotearg.h b/src/bin/m4/lib/quotearg.h deleted file mode 100644 index 4887df3b6d..0000000000 --- a/src/bin/m4/lib/quotearg.h +++ /dev/null @@ -1,140 +0,0 @@ -/* quotearg.h - quote arguments for output - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert */ - -#ifndef QUOTEARG_H_ -# define QUOTEARG_H_ 1 - -# include - -/* Basic quoting styles. */ -enum quoting_style - { - /* Output names as-is (ls --quoting-style=literal). */ - literal_quoting_style, - - /* Quote names for the shell if they contain shell metacharacters - or would cause ambiguous output (ls --quoting-style=shell). */ - shell_quoting_style, - - /* Quote names for the shell, even if they would normally not - require quoting (ls --quoting-style=shell-always). */ - shell_always_quoting_style, - - /* Quote names as for a C language string (ls --quoting-style=c). */ - c_quoting_style, - - /* Like c_quoting_style except omit the surrounding double-quote - characters (ls --quoting-style=escape). */ - escape_quoting_style, - - /* Like clocale_quoting_style, but quote `like this' instead of - "like this" in the default C locale (ls --quoting-style=locale). */ - locale_quoting_style, - - /* Like c_quoting_style except use quotation marks appropriate for - the locale (ls --quoting-style=clocale). */ - clocale_quoting_style - }; - -/* For now, --quoting-style=literal is the default, but this may change. */ -# ifndef DEFAULT_QUOTING_STYLE -# define DEFAULT_QUOTING_STYLE literal_quoting_style -# endif - -/* Names of quoting styles and their corresponding values. */ -extern char const *const quoting_style_args[]; -extern enum quoting_style const quoting_style_vals[]; - -struct quoting_options; - -/* The functions listed below set and use a hidden variable - that contains the default quoting style options. */ - -/* Allocate a new set of quoting options, with contents initially identical - to O if O is not null, or to the default if O is null. - It is the caller's responsibility to free the result. */ -struct quoting_options *clone_quoting_options (struct quoting_options *o); - -/* Get the value of O's quoting style. If O is null, use the default. */ -enum quoting_style get_quoting_style (struct quoting_options *o); - -/* In O (or in the default if O is null), - set the value of the quoting style to S. */ -void set_quoting_style (struct quoting_options *o, enum quoting_style s); - -/* In O (or in the default if O is null), - set the value of the quoting options for character C to I. - Return the old value. Currently, the only values defined for I are - 0 (the default) and 1 (which means to quote the character even if - it would not otherwise be quoted). */ -int set_char_quoting (struct quoting_options *o, char c, int i); - -/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of - argument ARG (of size ARGSIZE), using O to control quoting. - If O is null, use the default. - Terminate the output with a null character, and return the written - size of the output, not counting the terminating null. - If BUFFERSIZE is too small to store the output string, return the - value that would have been returned had BUFFERSIZE been large enough. - If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */ -size_t quotearg_buffer (char *buffer, size_t buffersize, - char const *arg, size_t argsize, - struct quoting_options const *o); - -/* Like quotearg_buffer, except return the result in a newly allocated - buffer. It is the caller's responsibility to free the result. */ -char *quotearg_alloc (char const *arg, size_t argsize, - struct quoting_options const *o); - -/* Use storage slot N to return a quoted version of the string ARG. - Use the default quoting options. - The returned value points to static storage that can be - reused by the next call to this function with the same value of N. - N must be nonnegative. */ -char *quotearg_n (int n, char const *arg); - -/* Equivalent to quotearg_n (0, ARG). */ -char *quotearg (char const *arg); - -/* Use style S and storage slot N to return a quoted version of the string ARG. - This is like quotearg_n (N, ARG), except that it uses S with no other - options to specify the quoting method. */ -char *quotearg_n_style (int n, enum quoting_style s, char const *arg); - -/* Use style S and storage slot N to return a quoted version of the - argument ARG of size ARGSIZE. This is like quotearg_n_style - (N, S, ARG), except it can quote null bytes. */ -char *quotearg_n_style_mem (int n, enum quoting_style s, - char const *arg, size_t argsize); - -/* Equivalent to quotearg_n_style (0, S, ARG). */ -char *quotearg_style (enum quoting_style s, char const *arg); - -/* Like quotearg (ARG), except also quote any instances of CH. */ -char *quotearg_char (char const *arg, char ch); - -/* Equivalent to quotearg_char (ARG, ':'). */ -char *quotearg_colon (char const *arg); - -/* Free any dynamically allocated memory. */ -void quotearg_free (void); - -#endif /* !QUOTEARG_H_ */ diff --git a/src/bin/m4/lib/regcomp.c b/src/bin/m4/lib/regcomp.c deleted file mode 100644 index 6e317f5134..0000000000 --- a/src/bin/m4/lib/regcomp.c +++ /dev/null @@ -1,3858 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, - size_t length, reg_syntax_t syntax); -static void re_compile_fastmap_iter (regex_t *bufp, - const re_dfastate_t *init_state, - char *fastmap); -static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); -#ifdef RE_ENABLE_I18N -static void free_charset (re_charset_t *cset); -#endif /* RE_ENABLE_I18N */ -static void free_workarea_compile (regex_t *preg); -static reg_errcode_t create_initial_state (re_dfa_t *dfa); -#ifdef RE_ENABLE_I18N -static void optimize_utf8 (re_dfa_t *dfa); -#endif -static reg_errcode_t analyze (regex_t *preg); -static reg_errcode_t preorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t postorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); -static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); -static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, - bin_tree_t *node); -static reg_errcode_t calc_first (void *extra, bin_tree_t *node); -static reg_errcode_t calc_next (void *extra, bin_tree_t *node); -static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); -static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint); -static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint); -static reg_errcode_t calc_eclosure (re_dfa_t *dfa); -static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, - Idx node, bool root); -static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); -static Idx fetch_number (re_string_t *input, re_token_t *token, - reg_syntax_t syntax); -static int peek_token (re_token_t *token, re_string_t *input, - reg_syntax_t syntax) internal_function; -static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, - re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, - reg_errcode_t *err); -static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token, int token_len, - re_dfa_t *dfa, - reg_syntax_t syntax, - bool accept_hyphen); -static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token); -#ifdef RE_ENABLE_I18N -static reg_errcode_t build_equiv_class (bitset_t sbcset, - re_charset_t *mbcset, - Idx *equiv_class_alloc, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - re_charset_t *mbcset, - Idx *char_class_alloc, - const unsigned char *class_name, - reg_syntax_t syntax); -#else /* not RE_ENABLE_I18N */ -static reg_errcode_t build_equiv_class (bitset_t sbcset, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - const unsigned char *class_name, - reg_syntax_t syntax); -#endif /* not RE_ENABLE_I18N */ -static bin_tree_t *build_charclass_op (re_dfa_t *dfa, - RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, - bool non_match, reg_errcode_t *err); -static bin_tree_t *create_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - re_token_type_t type); -static bin_tree_t *create_token_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - const re_token_t *token); -static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); -static void free_token (re_token_t *node); -static reg_errcode_t free_tree (void *extra, bin_tree_t *node); -static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -static const char __re_error_msgid[] = - { -#define REG_NOERROR_IDX 0 - gettext_noop ("Success") /* REG_NOERROR */ - "\0" -#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") - gettext_noop ("No match") /* REG_NOMATCH */ - "\0" -#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") - gettext_noop ("Invalid regular expression") /* REG_BADPAT */ - "\0" -#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") - gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ - "\0" -#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") - gettext_noop ("Invalid character class name") /* REG_ECTYPE */ - "\0" -#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") - gettext_noop ("Trailing backslash") /* REG_EESCAPE */ - "\0" -#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") - gettext_noop ("Invalid back reference") /* REG_ESUBREG */ - "\0" -#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") - gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ - "\0" -#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") - gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ - "\0" -#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") - gettext_noop ("Unmatched \\{") /* REG_EBRACE */ - "\0" -#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") - gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ - "\0" -#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") - gettext_noop ("Invalid range end") /* REG_ERANGE */ - "\0" -#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") - gettext_noop ("Memory exhausted") /* REG_ESPACE */ - "\0" -#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") - gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ - "\0" -#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") - gettext_noop ("Premature end of regular expression") /* REG_EEND */ - "\0" -#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") - gettext_noop ("Regular expression too big") /* REG_ESIZE */ - "\0" -#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") - gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ - }; - -static const size_t __re_error_msgid_idx[] = - { - REG_NOERROR_IDX, - REG_NOMATCH_IDX, - REG_BADPAT_IDX, - REG_ECOLLATE_IDX, - REG_ECTYPE_IDX, - REG_EESCAPE_IDX, - REG_ESUBREG_IDX, - REG_EBRACK_IDX, - REG_EPAREN_IDX, - REG_EBRACE_IDX, - REG_BADBR_IDX, - REG_ERANGE_IDX, - REG_ESPACE_IDX, - REG_BADRPT_IDX, - REG_EEND_IDX, - REG_ESIZE_IDX, - REG_ERPAREN_IDX - }; - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length LENGTH) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the `allocated' (and perhaps `buffer') and `translate' fields - are set in BUFP on entry. */ - -#ifdef _LIBC -const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - size_t length; - struct re_pattern_buffer *bufp; -#else /* size_t might promote */ -const char * -re_compile_pattern (const char *pattern, size_t length, - struct re_pattern_buffer *bufp) -#endif -{ - reg_errcode_t ret; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub, unless RE_NO_SUB is set. */ - bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = re_compile_internal (bufp, pattern, length, re_syntax_options); - - if (!ret) - return NULL; - return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} -#ifdef _LIBC -weak_alias (__re_compile_pattern, re_compile_pattern) -#endif - -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; - return ret; -} -#ifdef _LIBC -weak_alias (__re_set_syntax, re_set_syntax) -#endif - -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - char *fastmap = bufp->fastmap; - - memset (fastmap, '\0', sizeof (char) * SBC_MAX); - re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); - if (dfa->init_state != dfa->init_state_word) - re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); - if (dfa->init_state != dfa->init_state_nl) - re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); - if (dfa->init_state != dfa->init_state_begbuf) - re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); - bufp->fastmap_accurate = 1; - return 0; -} -#ifdef _LIBC -weak_alias (__re_compile_fastmap, re_compile_fastmap) -#endif - -static inline void -__attribute ((always_inline)) -re_set_fastmap (char *fastmap, bool icase, int ch) -{ - fastmap[ch] = 1; - if (icase) - fastmap[tolower (ch)] = 1; -} - -/* Helper function for re_compile_fastmap. - Compile fastmap for the initial_state INIT_STATE. */ - -static void -re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, - char *fastmap) -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - Idx node_cnt; - bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); - for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) - { - Idx node = init_state->nodes.elems[node_cnt]; - re_token_type_t type = dfa->nodes[node].type; - - if (type == CHARACTER) - { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); -#ifdef RE_ENABLE_I18N - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - unsigned char buf[MB_LEN_MAX]; - unsigned char *p; - wchar_t wc; - mbstate_t state; - - p = buf; - *p++ = dfa->nodes[node].opr.c; - while (++node < dfa->nodes_len - && dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].mb_partial) - *p++ = dfa->nodes[node].opr.c; - memset (&state, '\0', sizeof (state)); - if (mbrtowc (&wc, (const char *) buf, p - buf, - &state) == p - buf - && (__wcrtomb ((char *) buf, towlower (wc), &state) - != (size_t) -1)) - re_set_fastmap (fastmap, false, buf[0]); - } -#endif - } - else if (type == SIMPLE_BRACKET) - { - int i, ch; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - { - int j; - bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (w & ((bitset_word_t) 1 << j)) - re_set_fastmap (fastmap, icase, ch); - } - } -#ifdef RE_ENABLE_I18N - else if (type == COMPLEX_BRACKET) - { - Idx i; - re_charset_t *cset = dfa->nodes[node].opr.mbcset; - if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes - || cset->nranges || cset->nchar_classes) - { -# ifdef _LIBC - if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) - { - /* In this case we want to catch the bytes which are - the first byte of any collation elements. - e.g. In da_DK, we want to catch 'a' since "aa" - is a valid collation element, and don't catch - 'b' since 'b' is the only collation element - which starts from 'b'. */ - const int32_t *table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - for (i = 0; i < SBC_MAX; ++i) - if (table[i] < 0) - re_set_fastmap (fastmap, icase, i); - } -# else - if (dfa->mb_cur_max > 1) - for (i = 0; i < SBC_MAX; ++i) - if (__btowc (i) == WEOF) - re_set_fastmap (fastmap, icase, i); -# endif /* not _LIBC */ - } - for (i = 0; i < cset->nmbchars; ++i) - { - char buf[256]; - mbstate_t state; - memset (&state, '\0', sizeof (state)); - if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) - != (size_t) -1) - re_set_fastmap (fastmap, false, *(unsigned char *) buf); - } - } - } -#endif /* RE_ENABLE_I18N */ - else if (type == OP_PERIOD -#ifdef RE_ENABLE_I18N - || type == OP_UTF8_PERIOD -#endif /* RE_ENABLE_I18N */ - || type == END_OF_RE) - { - memset (fastmap, '\1', sizeof (char) * SBC_MAX); - if (type == END_OF_RE) - bufp->can_be_null = 1; - return; - } - } -} - -/* Entry point for POSIX code. */ -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' to an allocated space for the fastmap; - `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (preg, pattern, cflags) - regex_t *__restrict preg; - const char *__restrict pattern; - int cflags; -{ - reg_errcode_t ret; - reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED - : RE_SYNTAX_POSIX_BASIC); - - preg->buffer = NULL; - preg->allocated = 0; - preg->used = 0; - - /* Try to allocate space for the fastmap. */ - preg->fastmap = re_malloc (char, SBC_MAX); - if (BE (preg->fastmap == NULL, 0)) - return REG_ESPACE; - - syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - preg->no_sub = !!(cflags & REG_NOSUB); - preg->translate = NULL; - - ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) - ret = REG_EPAREN; - - /* We have already checked preg->fastmap != NULL. */ - if (BE (ret == REG_NOERROR, 1)) - /* Compute the fastmap now, since regexec cannot modify the pattern - buffer. This function never fails in this implementation. */ - (void) re_compile_fastmap (preg); - else - { - /* Some error occurred while compiling the expression. */ - re_free (preg->fastmap); - preg->fastmap = NULL; - } - - return (int) ret; -} -#ifdef _LIBC -weak_alias (__regcomp, regcomp) -#endif - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -#ifdef _LIBC -size_t -regerror (errcode, preg, errbuf, errbuf_size) - int errcode; - const regex_t *__restrict preg; - char *__restrict errbuf; - size_t errbuf_size; -#else /* size_t might promote */ -size_t -regerror (int errcode, const regex_t *__restrict preg, - char *__restrict errbuf, size_t errbuf_size) -#endif -{ - const char *msg; - size_t msg_size; - - if (BE (errcode < 0 - || errcode >= (int) (sizeof (__re_error_msgid_idx) - / sizeof (__re_error_msgid_idx[0])), 0)) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - abort (); - - msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (BE (errbuf_size != 0, 1)) - { - if (BE (msg_size > errbuf_size, 0)) - { -#if defined HAVE_MEMPCPY || defined _LIBC - *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; -#else - memcpy (errbuf, msg, errbuf_size - 1); - errbuf[errbuf_size - 1] = 0; -#endif - } - else - memcpy (errbuf, msg, msg_size); - } - - return msg_size; -} -#ifdef _LIBC -weak_alias (__regerror, regerror) -#endif - - -#ifdef RE_ENABLE_I18N -/* This static array is used for the map to single-byte characters when - UTF-8 is used. Otherwise we would allocate memory just to initialize - it the same all the time. UTF-8 is the preferred encoding so this is - a worthwhile optimization. */ -static const bitset_t utf8_sb_map = -{ - /* Set the first 128 bits. */ -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, -# endif - (BITSET_WORD_MAX - >> (SBC_MAX % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) -}; -#endif - - -static void -free_dfa_content (re_dfa_t *dfa) -{ - Idx i, j; - - if (dfa->nodes) - for (i = 0; i < dfa->nodes_len; ++i) - free_token (dfa->nodes + i); - re_free (dfa->nexts); - for (i = 0; i < dfa->nodes_len; ++i) - { - if (dfa->eclosures != NULL) - re_node_set_free (dfa->eclosures + i); - if (dfa->inveclosures != NULL) - re_node_set_free (dfa->inveclosures + i); - if (dfa->edests != NULL) - re_node_set_free (dfa->edests + i); - } - re_free (dfa->edests); - re_free (dfa->eclosures); - re_free (dfa->inveclosures); - re_free (dfa->nodes); - - if (dfa->state_table) - for (i = 0; i <= dfa->state_hash_mask; ++i) - { - struct re_state_table_entry *entry = dfa->state_table + i; - for (j = 0; j < entry->num; ++j) - { - re_dfastate_t *state = entry->array[j]; - free_state (state); - } - re_free (entry->array); - } - re_free (dfa->state_table); -#ifdef RE_ENABLE_I18N - if (dfa->sb_char != utf8_sb_map) - re_free (dfa->sb_char); -#endif - re_free (dfa->subexp_map); -#ifdef DEBUG - re_free (dfa->re_str); -#endif - - re_free (dfa); -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (preg) - regex_t *preg; -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - if (BE (dfa != NULL, 1)) - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - - re_free (preg->fastmap); - preg->fastmap = NULL; - - re_free (preg->translate); - preg->translate = NULL; -} -#ifdef _LIBC -weak_alias (__regfree, regfree) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -# ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec above without link errors. */ -weak_function -# endif -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - char *fastmap; - - if (!s) - { - if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); - return 0; - } - - if (re_comp_buf.buffer) - { - fastmap = re_comp_buf.fastmap; - re_comp_buf.fastmap = NULL; - __regfree (&re_comp_buf); - memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); - re_comp_buf.fastmap = fastmap; - } - - if (re_comp_buf.fastmap == NULL) - { - re_comp_buf.fastmap = (char *) malloc (SBC_MAX); - if (re_comp_buf.fastmap == NULL) - return (char *) gettext (__re_error_msgid - + __re_error_msgid_idx[(int) REG_ESPACE]); - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); - - if (!ret) - return NULL; - - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} - -#ifdef _LIBC -libc_freeres_fn (free_mem) -{ - __regfree (&re_comp_buf); -} -#endif - -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. - Compile the regular expression PATTERN, whose length is LENGTH. - SYNTAX indicate regular expression's syntax. */ - -static reg_errcode_t -re_compile_internal (regex_t *preg, const char * pattern, size_t length, - reg_syntax_t syntax) -{ - reg_errcode_t err = REG_NOERROR; - re_dfa_t *dfa; - re_string_t regexp; - - /* Initialize the pattern buffer. */ - preg->fastmap_accurate = 0; - preg->syntax = syntax; - preg->not_bol = preg->not_eol = 0; - preg->used = 0; - preg->re_nsub = 0; - preg->can_be_null = 0; - preg->regs_allocated = REGS_UNALLOCATED; - - /* Initialize the dfa. */ - dfa = (re_dfa_t *) preg->buffer; - if (BE (preg->allocated < sizeof (re_dfa_t), 0)) - { - /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. If ->buffer is NULL this - is a simple allocation. */ - dfa = re_realloc (preg->buffer, re_dfa_t, 1); - if (dfa == NULL) - return REG_ESPACE; - preg->allocated = sizeof (re_dfa_t); - preg->buffer = (unsigned char *) dfa; - } - preg->used = sizeof (re_dfa_t); - - err = init_dfa (dfa, length); - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } -#ifdef DEBUG - /* Note: length+1 will not overflow since it is checked in init_dfa. */ - dfa->re_str = re_malloc (char, length + 1); - strncpy (dfa->re_str, pattern, length + 1); -#endif - - __libc_lock_init (dfa->lock); - - err = re_string_construct (®exp, pattern, length, preg->translate, - syntax & RE_ICASE, dfa); - if (BE (err != REG_NOERROR, 0)) - { - re_compile_internal_free_return: - free_workarea_compile (preg); - re_string_destruct (®exp); - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } - - /* Parse the regular expression, and build a structure tree. */ - preg->re_nsub = 0; - dfa->str_tree = parse (®exp, preg, syntax, &err); - if (BE (dfa->str_tree == NULL, 0)) - goto re_compile_internal_free_return; - - /* Analyze the tree and create the nfa. */ - err = analyze (preg); - if (BE (err != REG_NOERROR, 0)) - goto re_compile_internal_free_return; - -#ifdef RE_ENABLE_I18N - /* If possible, do searching in single byte encoding to speed things up. */ - if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) - optimize_utf8 (dfa); -#endif - - /* Then create the initial state of the dfa. */ - err = create_initial_state (dfa); - - /* Release work areas. */ - free_workarea_compile (preg); - re_string_destruct (®exp); - - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - } - - return err; -} - -/* Initialize DFA. We use the length of the regular expression PAT_LEN - as the initial length of some arrays. */ - -static reg_errcode_t -init_dfa (re_dfa_t *dfa, size_t pat_len) -{ - __re_size_t table_size; -#ifndef _LIBC - char *codeset_name; -#endif -#ifdef RE_ENABLE_I18N - size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); -#else - size_t max_i18n_object_size = 0; -#endif - size_t max_object_size = - MAX (sizeof (struct re_state_table_entry), - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - MAX (sizeof (regmatch_t), - max_i18n_object_size)))); - - memset (dfa, '\0', sizeof (re_dfa_t)); - - /* Force allocation of str_tree_storage the first time. */ - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - - /* Avoid overflows. The extra "/ 2" is for the table_size doubling - calculation below, and for similar doubling calculations - elsewhere. And it's <= rather than <, because some of the - doubling calculations add 1 afterwards. */ - if (BE (SIZE_MAX / max_object_size / 2 <= pat_len, 0)) - return REG_ESPACE; - - dfa->nodes_alloc = pat_len + 1; - dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); - - /* table_size = 2 ^ ceil(log pat_len) */ - for (table_size = 1; ; table_size <<= 1) - if (table_size > pat_len) - break; - - dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); - dfa->state_hash_mask = table_size - 1; - - dfa->mb_cur_max = MB_CUR_MAX; -#ifdef _LIBC - if (dfa->mb_cur_max == 6 - && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) - dfa->is_utf8 = 1; - dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) - != 0); -#else -# ifdef HAVE_LANGINFO_CODESET - codeset_name = nl_langinfo (CODESET); -# else - codeset_name = getenv ("LC_ALL"); - if (codeset_name == NULL || codeset_name[0] == '\0') - codeset_name = getenv ("LC_CTYPE"); - if (codeset_name == NULL || codeset_name[0] == '\0') - codeset_name = getenv ("LANG"); - if (codeset_name == NULL) - codeset_name = ""; - else if (strchr (codeset_name, '.') != NULL) - codeset_name = strchr (codeset_name, '.') + 1; -# endif - - if (strcasecmp (codeset_name, "UTF-8") == 0 - || strcasecmp (codeset_name, "UTF8") == 0) - dfa->is_utf8 = 1; - - /* We check exhaustively in the loop below if this charset is a - superset of ASCII. */ - dfa->map_notascii = 0; -#endif - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - if (dfa->is_utf8) - dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; - else - { - int i, j, ch; - - dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - if (BE (dfa->sb_char == NULL, 0)) - return REG_ESPACE; - - /* Set the bits corresponding to single byte chars. */ - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - { - wint_t wch = __btowc (ch); - if (wch != WEOF) - dfa->sb_char[i] |= (bitset_word_t) 1 << j; -# ifndef _LIBC - if (isascii (ch) && wch != ch) - dfa->map_notascii = 1; -# endif - } - } - } -#endif - - if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -/* Initialize WORD_CHAR table, which indicate which character is - "word". In this case "word" means that it is the word construction - character used by some operators like "\<", "\>", etc. */ - -static void -internal_function -init_word_char (re_dfa_t *dfa) -{ - int i, j, ch; - dfa->word_ops_used = 1; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (isalnum (ch) || ch == '_') - dfa->word_char[i] |= (bitset_word_t) 1 << j; -} - -/* Free the work area which are only used while compiling. */ - -static void -free_workarea_compile (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_storage_t *storage, *next; - for (storage = dfa->str_tree_storage; storage; storage = next) - { - next = storage->next; - re_free (storage); - } - dfa->str_tree_storage = NULL; - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - dfa->str_tree = NULL; - re_free (dfa->org_indices); - dfa->org_indices = NULL; -} - -/* Create initial states for all contexts. */ - -static reg_errcode_t -create_initial_state (re_dfa_t *dfa) -{ - Idx first, i; - reg_errcode_t err; - re_node_set init_nodes; - - /* Initial states have the epsilon closure of the node which is - the first node of the regular expression. */ - first = dfa->str_tree->first->node_idx; - dfa->init_node = first; - err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* The back-references which are in initial states can epsilon transit, - since in this case all of the subexpressions can be null. - Then we add epsilon closures of the nodes which are the next nodes of - the back-references. */ - if (dfa->nbackref > 0) - for (i = 0; i < init_nodes.nelem; ++i) - { - Idx node_idx = init_nodes.elems[i]; - re_token_type_t type = dfa->nodes[node_idx].type; - - Idx clexp_idx; - if (type != OP_BACK_REF) - continue; - for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) - { - re_token_t *clexp_node; - clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; - if (clexp_node->type == OP_CLOSE_SUBEXP - && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) - break; - } - if (clexp_idx == init_nodes.nelem) - continue; - - if (type == OP_BACK_REF) - { - Idx dest_idx = dfa->edests[node_idx].elems[0]; - if (!re_node_set_contains (&init_nodes, dest_idx)) - { - re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - i = 0; - } - } - } - - /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ - if (BE (dfa->init_state == NULL, 0)) - return err; - if (dfa->init_state->has_constraint) - { - dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_WORD); - dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_NEWLINE); - dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, - &init_nodes, - CONTEXT_NEWLINE - | CONTEXT_BEGBUF); - if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return err; - } - else - dfa->init_state_word = dfa->init_state_nl - = dfa->init_state_begbuf = dfa->init_state; - - re_node_set_free (&init_nodes); - return REG_NOERROR; -} - -#ifdef RE_ENABLE_I18N -/* If it is possible to do searching in single byte encoding instead of UTF-8 - to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change - DFA nodes where needed. */ - -static void -optimize_utf8 (re_dfa_t *dfa) -{ - Idx node; - int i; - bool mb_chars = false; - bool has_period = false; - - for (node = 0; node < dfa->nodes_len; ++node) - switch (dfa->nodes[node].type) - { - case CHARACTER: - if (dfa->nodes[node].opr.c >= ASCII_CHARS) - mb_chars = true; - break; - case ANCHOR: - switch (dfa->nodes[node].opr.idx) - { - case LINE_FIRST: - case LINE_LAST: - case BUF_FIRST: - case BUF_LAST: - break; - default: - /* Word anchors etc. cannot be handled. */ - return; - } - break; - case OP_PERIOD: - has_period = true; - break; - case OP_BACK_REF: - case OP_ALT: - case END_OF_RE: - case OP_DUP_ASTERISK: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - break; - case COMPLEX_BRACKET: - return; - case SIMPLE_BRACKET: - /* Just double check. */ - { - int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS); - for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) - { - if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0) - return; - rshift = 0; - } - } - break; - default: - abort (); - } - - if (mb_chars || has_period) - for (node = 0; node < dfa->nodes_len; ++node) - { - if (dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].opr.c >= ASCII_CHARS) - dfa->nodes[node].mb_partial = 0; - else if (dfa->nodes[node].type == OP_PERIOD) - dfa->nodes[node].type = OP_UTF8_PERIOD; - } - - /* The search can be in single byte locale. */ - dfa->mb_cur_max = 1; - dfa->is_utf8 = 0; - dfa->has_mb_node = dfa->nbackref > 0 || has_period; -} -#endif - -/* Analyze the structure tree, and calculate "first", "next", "edest", - "eclosure", and "inveclosure". */ - -static reg_errcode_t -analyze (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - reg_errcode_t ret; - - /* Allocate arrays. */ - dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); - dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); - dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); - dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); - if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL - || dfa->eclosures == NULL, 0)) - return REG_ESPACE; - - dfa->subexp_map = re_malloc (Idx, preg->re_nsub); - if (dfa->subexp_map != NULL) - { - Idx i; - for (i = 0; i < preg->re_nsub; i++) - dfa->subexp_map[i] = i; - preorder (dfa->str_tree, optimize_subexps, dfa); - for (i = 0; i < preg->re_nsub; i++) - if (dfa->subexp_map[i] != i) - break; - if (i == preg->re_nsub) - { - free (dfa->subexp_map); - dfa->subexp_map = NULL; - } - } - - ret = postorder (dfa->str_tree, lower_subexps, preg); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = postorder (dfa->str_tree, calc_first, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - preorder (dfa->str_tree, calc_next, dfa); - ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = calc_eclosure (dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - /* We only need this during the prune_impossible_nodes pass in regexec.c; - skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ - if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) - || dfa->nbackref) - { - dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); - if (BE (dfa->inveclosures == NULL, 0)) - return REG_ESPACE; - ret = calc_inveclosure (dfa); - } - - return ret; -} - -/* Our parse trees are very unbalanced, so we cannot use a stack to - implement parse tree visits. Instead, we use parent pointers and - some hairy code in these two functions. */ -static reg_errcode_t -postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node, *prev; - - for (node = root; ; ) - { - /* Descend down the tree, preferably to the left (or to the right - if that's the only child). */ - while (node->left || node->right) - if (node->left) - node = node->left; - else - node = node->right; - - do - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - if (node->parent == NULL) - return REG_NOERROR; - prev = node; - node = node->parent; - } - /* Go up while we have a node that is reached from the right. */ - while (node->right == prev || node->right == NULL); - node = node->right; - } -} - -static reg_errcode_t -preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node; - - for (node = root; ; ) - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Go to the left node, or up and to the right. */ - if (node->left) - node = node->left; - else - { - bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - if (!node) - return REG_NOERROR; - } - node = node->right; - } - } -} - -/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell - re_search_internal to map the inner one's opr.idx to this one's. Adjust - backreferences as well. Requires a preorder visit. */ -static reg_errcode_t -optimize_subexps (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - - if (node->token.type == OP_BACK_REF && dfa->subexp_map) - { - int idx = node->token.opr.idx; - node->token.opr.idx = dfa->subexp_map[idx]; - dfa->used_bkref_map |= 1 << node->token.opr.idx; - } - - else if (node->token.type == SUBEXP - && node->left && node->left->token.type == SUBEXP) - { - Idx other_idx = node->left->token.opr.idx; - - node->left = node->left->left; - if (node->left) - node->left->parent = node; - - dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; - if (other_idx < BITSET_WORD_BITS) - dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); - } - - return REG_NOERROR; -} - -/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation - of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ -static reg_errcode_t -lower_subexps (void *extra, bin_tree_t *node) -{ - regex_t *preg = (regex_t *) extra; - reg_errcode_t err = REG_NOERROR; - - if (node->left && node->left->token.type == SUBEXP) - { - node->left = lower_subexp (&err, preg, node->left); - if (node->left) - node->left->parent = node; - } - if (node->right && node->right->token.type == SUBEXP) - { - node->right = lower_subexp (&err, preg, node->right); - if (node->right) - node->right->parent = node; - } - - return err; -} - -static bin_tree_t * -lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *body = node->left; - bin_tree_t *op, *cls, *tree1, *tree; - - if (preg->no_sub - /* We do not optimize empty subexpressions, because otherwise we may - have bad CONCAT nodes with NULL children. This is obviously not - very common, so we do not lose much. An example that triggers - this case is the sed "script" /\(\)/x. */ - && node->left != NULL - && (node->token.opr.idx >= BITSET_WORD_BITS - || !(dfa->used_bkref_map - & ((bitset_word_t) 1 << node->token.opr.idx)))) - return node->left; - - /* Convert the SUBEXP node to the concatenation of an - OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ - op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); - cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); - tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; - tree = create_tree (dfa, op, tree1, CONCAT); - if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - - op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; - op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; - return tree; -} - -/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton - nodes. Requires a postorder visit. */ -static reg_errcode_t -calc_first (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - if (node->token.type == CONCAT) - { - node->first = node->left->first; - node->node_idx = node->left->node_idx; - } - else - { - node->first = node; - node->node_idx = re_dfa_add_node (dfa, node->token); - if (BE (node->node_idx == REG_MISSING, 0)) - return REG_ESPACE; - } - return REG_NOERROR; -} - -/* Pass 2: compute NEXT on the tree. Preorder visit. */ -static reg_errcode_t -calc_next (void *extra, bin_tree_t *node) -{ - switch (node->token.type) - { - case OP_DUP_ASTERISK: - node->left->next = node; - break; - case CONCAT: - node->left->next = node->right->first; - node->right->next = node->next; - break; - default: - if (node->left) - node->left->next = node->next; - if (node->right) - node->right->next = node->next; - break; - } - return REG_NOERROR; -} - -/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ -static reg_errcode_t -link_nfa_nodes (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - Idx idx = node->node_idx; - reg_errcode_t err = REG_NOERROR; - - switch (node->token.type) - { - case CONCAT: - break; - - case END_OF_RE: - assert (node->next == NULL); - break; - - case OP_DUP_ASTERISK: - case OP_ALT: - { - Idx left, right; - dfa->has_plural_match = 1; - if (node->left != NULL) - left = node->left->first->node_idx; - else - left = node->next->node_idx; - if (node->right != NULL) - right = node->right->first->node_idx; - else - right = node->next->node_idx; - assert (REG_VALID_INDEX (left)); - assert (REG_VALID_INDEX (right)); - err = re_node_set_init_2 (dfa->edests + idx, left, right); - } - break; - - case ANCHOR: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); - break; - - case OP_BACK_REF: - dfa->nexts[idx] = node->next->node_idx; - if (node->token.type == OP_BACK_REF) - re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); - break; - - default: - assert (!IS_EPSILON_NODE (node->token.type)); - dfa->nexts[idx] = node->next->node_idx; - break; - } - - return err; -} - -/* Duplicate the epsilon closure of the node ROOT_NODE. - Note that duplicated nodes have constraint INIT_CONSTRAINT in addition - to their own constraint. */ - -static reg_errcode_t -internal_function -duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, - Idx root_node, unsigned int init_constraint) -{ - Idx org_node, clone_node; - bool ok; - unsigned int constraint = init_constraint; - for (org_node = top_org_node, clone_node = top_clone_node;;) - { - Idx org_dest, clone_dest; - if (dfa->nodes[org_node].type == OP_BACK_REF) - { - /* If the back reference epsilon-transit, its destination must - also have the constraint. Then duplicate the epsilon closure - of the destination of the back reference, and store it in - edests of the back reference. */ - org_dest = dfa->nexts[org_node]; - re_node_set_empty (dfa->edests + clone_node); - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - dfa->nexts[clone_node] = dfa->nexts[org_node]; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - else if (dfa->edests[org_node].nelem == 0) - { - /* In case of the node can't epsilon-transit, don't duplicate the - destination and store the original destination as the - destination of the node. */ - dfa->nexts[clone_node] = dfa->nexts[org_node]; - break; - } - else if (dfa->edests[org_node].nelem == 1) - { - /* In case of the node can epsilon-transit, and it has only one - destination. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - if (dfa->nodes[org_node].type == ANCHOR) - { - /* In case of the node has another constraint, append it. */ - if (org_node == root_node && clone_node != org_node) - { - /* ...but if the node is root_node itself, it means the - epsilon closure have a loop, then tie it to the - destination of the root_node. */ - ok = re_node_set_insert (dfa->edests + clone_node, org_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - break; - } - constraint |= dfa->nodes[org_node].opr.ctx_type; - } - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - else /* dfa->edests[org_node].nelem == 2 */ - { - /* In case of the node can epsilon-transit, and it has two - destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* Search for a duplicated node which satisfies the constraint. */ - clone_dest = search_duplicated_node (dfa, org_dest, constraint); - if (clone_dest == REG_MISSING) - { - /* There are no such a duplicated node, create a new one. */ - reg_errcode_t err; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - err = duplicate_node_closure (dfa, org_dest, clone_dest, - root_node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - { - /* There are a duplicated node which satisfy the constraint, - use it to avoid infinite loop. */ - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - - org_dest = dfa->edests[org_node].elems[1]; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - org_node = org_dest; - clone_node = clone_dest; - } - return REG_NOERROR; -} - -/* Search for a node which is duplicated from the node ORG_NODE, and - satisfies the constraint CONSTRAINT. */ - -static Idx -search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint) -{ - Idx idx; - for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) - { - if (org_node == dfa->org_indices[idx] - && constraint == dfa->nodes[idx].constraint) - return idx; /* Found. */ - } - return REG_MISSING; /* Not found. */ -} - -/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. - Return the index of the new node, or REG_MISSING if insufficient storage is - available. */ - -static Idx -duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) -{ - Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); - if (BE (dup_idx != REG_MISSING, 1)) - { - dfa->nodes[dup_idx].constraint = constraint; - if (dfa->nodes[org_idx].type == ANCHOR) - dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; - dfa->nodes[dup_idx].duplicated = 1; - - /* Store the index of the original node. */ - dfa->org_indices[dup_idx] = org_idx; - } - return dup_idx; -} - -static reg_errcode_t -calc_inveclosure (re_dfa_t *dfa) -{ - Idx src, idx; - bool ok; - for (idx = 0; idx < dfa->nodes_len; ++idx) - re_node_set_init_empty (dfa->inveclosures + idx); - - for (src = 0; src < dfa->nodes_len; ++src) - { - Idx *elems = dfa->eclosures[src].elems; - for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) - { - ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); - if (BE (! ok, 0)) - return REG_ESPACE; - } - } - - return REG_NOERROR; -} - -/* Calculate "eclosure" for all the node in DFA. */ - -static reg_errcode_t -calc_eclosure (re_dfa_t *dfa) -{ - Idx node_idx; - bool incomplete; -#ifdef DEBUG - assert (dfa->nodes_len > 0); -#endif - incomplete = false; - /* For each nodes, calculate epsilon closure. */ - for (node_idx = 0; ; ++node_idx) - { - reg_errcode_t err; - re_node_set eclosure_elem; - if (node_idx == dfa->nodes_len) - { - if (!incomplete) - break; - incomplete = false; - node_idx = 0; - } - -#ifdef DEBUG - assert (dfa->eclosures[node_idx].nelem != REG_MISSING); -#endif - - /* If we have already calculated, skip it. */ - if (dfa->eclosures[node_idx].nelem != 0) - continue; - /* Calculate epsilon closure of `node_idx'. */ - err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (dfa->eclosures[node_idx].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - return REG_NOERROR; -} - -/* Calculate epsilon closure of NODE. */ - -static reg_errcode_t -calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) -{ - reg_errcode_t err; - unsigned int constraint; - Idx i; - bool incomplete; - bool ok; - re_node_set eclosure; - incomplete = false; - err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* This indicates that we are calculating this node now. - We reference this value to avoid infinite loop. */ - dfa->eclosures[node].nelem = REG_MISSING; - - constraint = ((dfa->nodes[node].type == ANCHOR) - ? dfa->nodes[node].opr.ctx_type : 0); - /* If the current node has constraints, duplicate all nodes. - Since they must inherit the constraints. */ - if (constraint - && dfa->edests[node].nelem - && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) - { - err = duplicate_node_closure (dfa, node, node, node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) - for (i = 0; i < dfa->edests[node].nelem; ++i) - { - re_node_set eclosure_elem; - Idx edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of `edest' is in progress, - return intermediate result. */ - if (dfa->eclosures[edest].nelem == REG_MISSING) - { - incomplete = true; - continue; - } - /* If we haven't calculated the epsilon closure of `edest' yet, - calculate now. Otherwise use calculated epsilon closure. */ - if (dfa->eclosures[edest].nelem == 0) - { - err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of `edest'. */ - re_node_set_merge (&eclosure, &eclosure_elem); - /* If the epsilon closure of `edest' is incomplete, - the epsilon closure of this node is also incomplete. */ - if (dfa->eclosures[edest].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - - /* Epsilon closures include itself. */ - ok = re_node_set_insert (&eclosure, node); - if (BE (! ok, 0)) - return REG_ESPACE; - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; - else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; -} - -/* Functions for token which are used in the parser. */ - -/* Fetch a token from INPUT. - We must not use this function inside bracket expressions. */ - -static void -internal_function -fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) -{ - re_string_skip_bytes (input, peek_token (result, input, syntax)); -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function inside bracket expressions. */ - -static int -internal_function -peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - - c = re_string_peek_byte (input, 0); - token->opr.c = c; - - token->word_char = 0; -#ifdef RE_ENABLE_I18N - token->mb_partial = 0; - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - token->mb_partial = 1; - return 1; - } -#endif - if (c == '\\') - { - unsigned char c2; - if (re_string_cur_idx (input) + 1 >= re_string_length (input)) - { - token->type = BACK_SLASH; - return 1; - } - - c2 = re_string_peek_byte_case (input, 1); - token->opr.c = c2; - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, - re_string_cur_idx (input) + 1); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (c2) != 0; - - switch (c2) - { - case '|': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (!(syntax & RE_NO_BK_REFS)) - { - token->type = OP_BACK_REF; - token->opr.idx = c2 - '1'; - } - break; - case '<': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_FIRST; - } - break; - case '>': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_LAST; - } - break; - case 'b': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_DELIM; - } - break; - case 'B': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = NOT_WORD_DELIM; - } - break; - case 'w': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_WORD; - break; - case 'W': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTWORD; - break; - case 's': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_SPACE; - break; - case 'S': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTSPACE; - break; - case '`': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_FIRST; - } - break; - case '\'': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_LAST; - } - break; - case '(': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_CLOSE_SUBEXP; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_CLOSE_DUP_NUM; - break; - default: - break; - } - return 2; - } - - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (token->opr.c); - - switch (c) - { - case '\n': - if (syntax & RE_NEWLINE_ALT) - token->type = OP_ALT; - break; - case '|': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '*': - token->type = OP_DUP_ASTERISK; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_CLOSE_DUP_NUM; - break; - case '(': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_CLOSE_SUBEXP; - break; - case '[': - token->type = OP_OPEN_BRACKET; - break; - case '.': - token->type = OP_PERIOD; - break; - case '^': - if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && - re_string_cur_idx (input) != 0) - { - char prev = re_string_peek_byte (input, -1); - if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_FIRST; - break; - case '$': - if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && - re_string_cur_idx (input) + 1 != re_string_length (input)) - { - re_token_t next; - re_string_skip_bytes (input, 1); - peek_token (&next, input, syntax); - re_string_skip_bytes (input, -1); - if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_LAST; - break; - default: - break; - } - return 1; -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function out of bracket expressions. */ - -static int -internal_function -peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - c = re_string_peek_byte (input, 0); - token->opr.c = c; - -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - return 1; - } -#endif /* RE_ENABLE_I18N */ - - if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) - && re_string_cur_idx (input) + 1 < re_string_length (input)) - { - /* In this case, '\' escape a character. */ - unsigned char c2; - re_string_skip_bytes (input, 1); - c2 = re_string_peek_byte (input, 0); - token->opr.c = c2; - token->type = CHARACTER; - return 1; - } - if (c == '[') /* '[' is a special char in a bracket exps. */ - { - unsigned char c2; - int token_len; - if (re_string_cur_idx (input) + 1 < re_string_length (input)) - c2 = re_string_peek_byte (input, 1); - else - c2 = 0; - token->opr.c = c2; - token_len = 2; - switch (c2) - { - case '.': - token->type = OP_OPEN_COLL_ELEM; - break; - case '=': - token->type = OP_OPEN_EQUIV_CLASS; - break; - case ':': - if (syntax & RE_CHAR_CLASSES) - { - token->type = OP_OPEN_CHAR_CLASS; - break; - } - /* else fall through. */ - default: - token->type = CHARACTER; - token->opr.c = c; - token_len = 1; - break; - } - return token_len; - } - switch (c) - { - case '-': - token->type = OP_CHARSET_RANGE; - break; - case ']': - token->type = OP_CLOSE_BRACKET; - break; - case '^': - token->type = OP_NON_MATCH_LIST; - break; - default: - token->type = CHARACTER; - } - return 1; -} - -/* Functions for parser. */ - -/* Entry point of the parser. - Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. - This function build the following tree, from regular expression : - CAT - / \ - / \ - EOR - - CAT means concatenation. - EOR means end of regular expression. */ - -static bin_tree_t * -parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, - reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *eor, *root; - re_token_t current_token; - dfa->syntax = syntax; - fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); - tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - eor = create_tree (dfa, NULL, NULL, END_OF_RE); - if (tree != NULL) - root = create_tree (dfa, tree, eor, CONCAT); - else - root = eor; - if (BE (eor == NULL || root == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - return root; -} - -/* This function build the following tree, from regular expression - |: - ALT - / \ - / \ - - - ALT means alternative, which represents the operator `|'. */ - -static bin_tree_t * -parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *branch = NULL; - tree = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type == OP_ALT) - { - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - if (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - branch = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && branch == NULL, 0)) - return NULL; - } - else - branch = NULL; - tree = create_tree (dfa, tree, branch, OP_ALT); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - return tree; -} - -/* This function build the following tree, from regular expression - : - CAT - / \ - / \ - - - CAT means concatenation. */ - -static bin_tree_t * -parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - bin_tree_t *tree, *exp; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - tree = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - exp = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && exp == NULL, 0)) - { - return NULL; - } - if (tree != NULL && exp != NULL) - { - tree = create_tree (dfa, tree, exp, CONCAT); - if (tree == NULL) - { - *err = REG_ESPACE; - return NULL; - } - } - else if (tree == NULL) - tree = exp; - /* Otherwise exp == NULL, we don't need to create new tree. */ - } - return tree; -} - -/* This function build the following tree, from regular expression a*: - * - | - a -*/ - -static bin_tree_t * -parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - switch (token->type) - { - case CHARACTER: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (!re_string_eoi (regexp) - && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) - { - bin_tree_t *mbc_remain; - fetch_token (token, regexp, syntax); - mbc_remain = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree, mbc_remain, CONCAT); - if (BE (mbc_remain == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - } -#endif - break; - case OP_OPEN_SUBEXP: - tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_OPEN_BRACKET: - tree = parse_bracket_exp (regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_BACK_REF: - if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) - { - *err = REG_ESUBREG; - return NULL; - } - dfa->used_bkref_map |= 1 << token->opr.idx; - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - ++dfa->nbackref; - dfa->has_mb_node = 1; - break; - case OP_OPEN_DUP_NUM: - if (syntax & RE_CONTEXT_INVALID_DUP) - { - *err = REG_BADRPT; - return NULL; - } - /* FALLTHROUGH */ - case OP_DUP_ASTERISK: - case OP_DUP_PLUS: - case OP_DUP_QUESTION: - if (syntax & RE_CONTEXT_INVALID_OPS) - { - *err = REG_BADRPT; - return NULL; - } - else if (syntax & RE_CONTEXT_INDEP_OPS) - { - fetch_token (token, regexp, syntax); - return parse_expression (regexp, preg, token, syntax, nest, err); - } - /* else fall through */ - case OP_CLOSE_SUBEXP: - if ((token->type == OP_CLOSE_SUBEXP) && - !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) - { - *err = REG_ERPAREN; - return NULL; - } - /* else fall through */ - case OP_CLOSE_DUP_NUM: - /* We treat it as a normal character. */ - - /* Then we can these characters as normal characters. */ - token->type = CHARACTER; - /* mb_partial and word_char bits should be initialized already - by peek_token. */ - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - break; - case ANCHOR: - if ((token->opr.ctx_type - & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) - && dfa->word_ops_used == 0) - init_word_char (dfa); - if (token->opr.ctx_type == WORD_DELIM - || token->opr.ctx_type == NOT_WORD_DELIM) - { - bin_tree_t *tree_first, *tree_last; - if (token->opr.ctx_type == WORD_DELIM) - { - token->opr.ctx_type = WORD_FIRST; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = WORD_LAST; - } - else - { - token->opr.ctx_type = INSIDE_WORD; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = INSIDE_NOTWORD; - } - tree_last = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree_first, tree_last, OP_ALT); - if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - else - { - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - /* We must return here, since ANCHORs can't be followed - by repetition operators. - eg. RE"^*" is invalid or "", - it must not be "". */ - fetch_token (token, regexp, syntax); - return tree; - case OP_PERIOD: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - if (dfa->mb_cur_max > 1) - dfa->has_mb_node = 1; - break; - case OP_WORD: - case OP_NOTWORD: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "alnum", - (const unsigned char *) "_", - token->type == OP_NOTWORD, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_SPACE: - case OP_NOTSPACE: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "space", - (const unsigned char *) "", - token->type == OP_NOTSPACE, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_ALT: - case END_OF_RE: - return NULL; - case BACK_SLASH: - *err = REG_EESCAPE; - return NULL; - default: - /* Must not happen? */ -#ifdef DEBUG - assert (0); -#endif - return NULL; - } - fetch_token (token, regexp, syntax); - - while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS - || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) - { - tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - /* In BRE consecutive duplications are not allowed. */ - if ((syntax & RE_CONTEXT_INVALID_DUP) - && (token->type == OP_DUP_ASTERISK - || token->type == OP_OPEN_DUP_NUM)) - { - *err = REG_BADRPT; - return NULL; - } - } - - return tree; -} - -/* This function build the following tree, from regular expression - (): - SUBEXP - | - -*/ - -static bin_tree_t * -parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - size_t cur_nsub; - cur_nsub = preg->re_nsub++; - - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - - /* The subexpression may be a null string. */ - if (token->type == OP_CLOSE_SUBEXP) - tree = NULL; - else - { - tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); - if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) - *err = REG_EPAREN; - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - - if (cur_nsub <= '9' - '1') - dfa->completed_bkref_map |= 1 << cur_nsub; - - tree = create_tree (dfa, tree, NULL, SUBEXP); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - tree->token.opr.idx = cur_nsub; - return tree; -} - -/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ - -static bin_tree_t * -parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) -{ - bin_tree_t *tree = NULL, *old_tree = NULL; - Idx i, start, end, start_idx = re_string_cur_idx (regexp); - re_token_t start_token = *token; - - if (token->type == OP_OPEN_DUP_NUM) - { - end = 0; - start = fetch_number (regexp, token, syntax); - if (start == REG_MISSING) - { - if (token->type == CHARACTER && token->opr.c == ',') - start = 0; /* We treat "{,m}" as "{0,m}". */ - else - { - *err = REG_BADBR; /* {} is invalid. */ - return NULL; - } - } - if (BE (start != REG_ERROR, 1)) - { - /* We treat "{n}" as "{n,n}". */ - end = ((token->type == OP_CLOSE_DUP_NUM) ? start - : ((token->type == CHARACTER && token->opr.c == ',') - ? fetch_number (regexp, token, syntax) : REG_ERROR)); - } - if (BE (start == REG_ERROR || end == REG_ERROR, 0)) - { - /* Invalid sequence. */ - if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) - { - if (token->type == END_OF_RE) - *err = REG_EBRACE; - else - *err = REG_BADBR; - - return NULL; - } - - /* If the syntax bit is set, rollback. */ - re_string_set_index (regexp, start_idx); - *token = start_token; - token->type = CHARACTER; - /* mb_partial and word_char bits should be already initialized by - peek_token. */ - return elem; - } - - if (BE (end != REG_MISSING && start > end, 0)) - { - /* First number greater than second. */ - *err = REG_BADBR; - return NULL; - } - } - else - { - start = (token->type == OP_DUP_PLUS) ? 1 : 0; - end = (token->type == OP_DUP_QUESTION) ? 1 : REG_MISSING; - } - - fetch_token (token, regexp, syntax); - - if (BE (elem == NULL, 0)) - return NULL; - if (BE (start == 0 && end == 0, 0)) - { - postorder (elem, free_tree, NULL); - return NULL; - } - - /* Extract "{n,m}" to "...{0,}". */ - if (BE (start > 0, 0)) - { - tree = elem; - for (i = 2; i <= start; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (start == end) - return tree; - - /* Duplicate ELEM before it is marked optional. */ - elem = duplicate_tree (elem, dfa); - old_tree = tree; - } - else - old_tree = NULL; - - if (elem->token.type == SUBEXP) - postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); - - tree = create_tree (dfa, elem, NULL, - (end == REG_MISSING ? OP_DUP_ASTERISK : OP_ALT)); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - - /* This loop is actually executed only when end != REG_MISSING, - to rewrite {0,n} as ((...?)?)?... We have - already created the start+1-th copy. */ - if ((Idx) -1 < 0 || end != REG_MISSING) - for (i = start + 2; i <= end; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - - tree = create_tree (dfa, tree, NULL, OP_ALT); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (old_tree) - tree = create_tree (dfa, old_tree, tree, CONCAT); - - return tree; - - parse_dup_op_espace: - *err = REG_ESPACE; - return NULL; -} - -/* Size of the names for collating symbol/equivalence_class/character_class. - I'm not sure, but maybe enough. */ -#define BRACKET_NAME_BUF_SIZE 32 - -#ifndef _LIBC - /* Local function for parse_bracket_exp only used in case of NOT _LIBC. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - -static reg_errcode_t -internal_function -# ifdef RE_ENABLE_I18N -build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, - bracket_elem_t *start_elem, bracket_elem_t *end_elem) -# else /* not RE_ENABLE_I18N */ -build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, - bracket_elem_t *end_elem) -# endif /* not RE_ENABLE_I18N */ -{ - unsigned int start_ch, end_ch; - /* Equivalence Classes and Character Classes can't be a range start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - /* We can handle no multi character collating elements without libc - support. */ - if (BE ((start_elem->type == COLL_SYM - && strlen ((char *) start_elem->opr.name) > 1) - || (end_elem->type == COLL_SYM - && strlen ((char *) end_elem->opr.name) > 1), 0)) - return REG_ECOLLATE; - -# ifdef RE_ENABLE_I18N - { - wchar_t wc; - wint_t start_wc; - wint_t end_wc; - wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - - start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) - ? __btowc (start_ch) : start_elem->opr.wch); - end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) - ? __btowc (end_ch) : end_elem->opr.wch); - if (start_wc == WEOF || end_wc == WEOF) - return REG_ECOLLATE; - cmp_buf[0] = start_wc; - cmp_buf[4] = end_wc; - if (wcscoll (cmp_buf, cmp_buf + 4) > 0) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes - no MBCSET if dfa->mb_cur_max == 1. */ - if (mbcset) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - wchar_t *new_array_start, *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - /* Use realloc since mbcset->range_starts and mbcset->range_ends - are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, wchar_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_wc; - mbcset->range_ends[mbcset->nranges++] = end_wc; - } - - /* Build the table for single byte characters. */ - for (wc = 0; wc < SBC_MAX; ++wc) - { - cmp_buf[2] = wc; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - bitset_set (sbcset, wc); - } - } -# else /* not RE_ENABLE_I18N */ - { - unsigned int ch; - start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - if (start_ch > end_ch) - return REG_ERANGE; - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ++ch) - if (start_ch <= ch && ch <= end_ch) - bitset_set (sbcset, ch); - } -# endif /* not RE_ENABLE_I18N */ - return REG_NOERROR; -} -#endif /* not _LIBC */ - -#ifndef _LIBC -/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ - -static reg_errcode_t -internal_function -build_collating_symbol (bitset_t sbcset, -# ifdef RE_ENABLE_I18N - re_charset_t *mbcset, Idx *coll_sym_alloc, -# endif - const unsigned char *name) -{ - size_t name_len = strlen ((const char *) name); - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } -} -#endif /* not _LIBC */ - -/* This function parse bracket expression like "[abc]", "[a-c]", - "[[.a-a.]]" etc. */ - -static bin_tree_t * -parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err) -{ -#ifdef _LIBC - const unsigned char *collseqmb; - const char *collseqwc; - uint32_t nrules; - int32_t table_size; - const int32_t *symb_table; - const unsigned char *extra; - - /* Local function for parse_bracket_exp used in _LIBC environement. - Seek the collating symbol entry correspondings to NAME. - Return the index of the symbol in the SYMB_TABLE. */ - - auto inline int32_t - __attribute ((always_inline)) - seek_collating_symbol_entry (name, name_len) - const unsigned char *name; - size_t name_len; - { - int32_t hash = elem_hash ((const char *) name, name_len); - int32_t elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - int32_t second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - /* Compare the length of the name. */ - && name_len == extra[symb_table[2 * elem + 1]] - /* Compare the name. */ - && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], - name_len) == 0) - { - /* Yep, this is the entry. */ - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - return elem; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Look up the collation sequence value of BR_ELEM. - Return the value if succeeded, UINT_MAX otherwise. */ - - auto inline unsigned int - __attribute ((always_inline)) - lookup_collation_sequence_value (br_elem) - bracket_elem_t *br_elem; - { - if (br_elem->type == SB_CHAR) - { - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - return collseqmb[br_elem->opr.ch]; - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } - else if (br_elem->type == MB_CHAR) - { - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); - } - else if (br_elem->type == COLL_SYM) - { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); - if (nrules != 0) - { - int32_t elem, idx; - elem = seek_collating_symbol_entry (br_elem->opr.name, - sym_name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - /* Skip the byte sequence of the collating element. */ - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the multibyte collation sequence value. */ - idx += sizeof (unsigned int); - /* Skip the wide char sequence of the collating element. */ - idx += sizeof (unsigned int) * - (1 + *(unsigned int *) (extra + idx)); - /* Return the collation sequence value. */ - return *(unsigned int *) (extra + idx); - } - else if (symb_table[2 * elem] == 0 && sym_name_len == 1) - { - /* No valid character. Match it as a single byte - character. */ - return collseqmb[br_elem->opr.name[0]]; - } - } - else if (sym_name_len == 1) - return collseqmb[br_elem->opr.name[0]]; - } - return UINT_MAX; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) - re_charset_t *mbcset; - Idx *range_alloc; - bitset_t sbcset; - bracket_elem_t *start_elem, *end_elem; - { - unsigned int ch; - uint32_t start_collseq; - uint32_t end_collseq; - - /* Equivalence Classes and Character Classes can't be a range - start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - start_collseq = lookup_collation_sequence_value (start_elem); - end_collseq = lookup_collation_sequence_value (end_elem); - /* Check start/end collation sequence values. */ - if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) - return REG_ECOLLATE; - if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ - if (nrules > 0 || dfa->mb_cur_max > 1) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - uint32_t *new_array_start; - uint32_t *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, uint32_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_collseq; - mbcset->range_ends[mbcset->nranges++] = end_collseq; - } - - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ch++) - { - uint32_t ch_collseq; - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - ch_collseq = collseqmb[ch]; - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) - bitset_set (sbcset, ch); - } - return REG_NOERROR; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument sinse we may update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) - re_charset_t *mbcset; - Idx *coll_sym_alloc; - bitset_t sbcset; - const unsigned char *name; - { - int32_t elem, idx; - size_t name_len = strlen ((const char *) name); - if (nrules != 0) - { - elem = seek_collating_symbol_entry (name, name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - } - else if (symb_table[2 * elem] == 0 && name_len == 1) - { - /* No valid character, treat it as a normal - character. */ - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - else - return REG_ECOLLATE; - - /* Got valid collation sequence, add it as a new entry. */ - /* Check the space of the arrays. */ - if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; - /* Use realloc since mbcset->coll_syms is NULL - if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); - if (BE (new_coll_syms == NULL, 0)) - return REG_ESPACE; - mbcset->coll_syms = new_coll_syms; - *coll_sym_alloc = new_coll_sym_alloc; - } - mbcset->coll_syms[mbcset->ncoll_syms++] = idx; - return REG_NOERROR; - } - else - { - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - } - } -#endif - - re_token_t br_token; - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; - Idx equiv_class_alloc = 0, char_class_alloc = 0; -#endif /* not RE_ENABLE_I18N */ - bool non_match = false; - bin_tree_t *work_tree; - int token_len; - bool first_round = true; -#ifdef _LIBC - collseqmb = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules) - { - /* - if (MB_CUR_MAX > 1) - */ - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - } -#endif - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else - if (BE (sbcset == NULL, 0)) -#endif /* RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_NON_MATCH_LIST) - { -#ifdef RE_ENABLE_I18N - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - non_match = true; - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set (sbcset, '\0'); - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - } - - /* We treat the first ']' as a normal character. */ - if (token->type == OP_CLOSE_BRACKET) - token->type = CHARACTER; - - while (1) - { - bracket_elem_t start_elem, end_elem; - unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; - unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; - reg_errcode_t ret; - int token_len2 = 0; - bool is_range_exp = false; - re_token_t token2; - - start_elem.opr.name = start_name_buf; - ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, - syntax, first_round); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - first_round = false; - - /* Get information about the next token. We need it in any case. */ - token_len = peek_token_bracket (token, regexp, syntax); - - /* Do not check for ranges if we know they are not allowed. */ - if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) - { - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CHARSET_RANGE) - { - re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ - token_len2 = peek_token_bracket (&token2, regexp, syntax); - if (BE (token2.type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token2.type == OP_CLOSE_BRACKET) - { - /* We treat the last '-' as a normal character. */ - re_string_skip_bytes (regexp, -token_len); - token->type = CHARACTER; - } - else - is_range_exp = true; - } - } - - if (is_range_exp == true) - { - end_elem.opr.name = end_name_buf; - ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, - dfa, syntax, true); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - - token_len = peek_token_bracket (token, regexp, syntax); - -#ifdef _LIBC - *err = build_range_exp (sbcset, mbcset, &range_alloc, - &start_elem, &end_elem); -#else -# ifdef RE_ENABLE_I18N - *err = build_range_exp (sbcset, - dfa->mb_cur_max > 1 ? mbcset : NULL, - &range_alloc, &start_elem, &end_elem); -# else - *err = build_range_exp (sbcset, &start_elem, &end_elem); -# endif -#endif /* RE_ENABLE_I18N */ - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - } - else - { - switch (start_elem.type) - { - case SB_CHAR: - bitset_set (sbcset, start_elem.opr.ch); - break; -#ifdef RE_ENABLE_I18N - case MB_CHAR: - /* Check whether the array has enough space. */ - if (BE (mbchar_alloc == mbcset->nmbchars, 0)) - { - wchar_t *new_mbchars; - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nmbchars is 0. */ - mbchar_alloc = 2 * mbcset->nmbchars + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - new_mbchars = re_realloc (mbcset->mbchars, wchar_t, - mbchar_alloc); - if (BE (new_mbchars == NULL, 0)) - goto parse_bracket_exp_espace; - mbcset->mbchars = new_mbchars; - } - mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; - break; -#endif /* RE_ENABLE_I18N */ - case EQUIV_CLASS: - *err = build_equiv_class (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &equiv_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case COLL_SYM: - *err = build_collating_symbol (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &coll_sym_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case CHAR_CLASS: - *err = build_charclass (regexp->trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &char_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name, syntax); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - default: - assert (0); - break; - } - } - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CLOSE_BRACKET) - break; - } - - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); - - if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes - || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes - || mbcset->non_match))) - { - bin_tree_t *mbc_tree; - int sbc_idx; - /* Build a tree for complex bracket. */ - dfa->has_mb_node = 1; - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto parse_bracket_exp_espace; - for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) - if (sbcset[sbc_idx]) - break; - /* If there are no bits set in sbcset, there is no point - of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ - if (sbc_idx < BITSET_WORDS) - { - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - - /* Then join them by ALT node. */ - work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - else - { - re_free (sbcset); - work_tree = mbc_tree; - } - } - else -#endif /* not RE_ENABLE_I18N */ - { -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - return work_tree; - - parse_bracket_exp_espace: - *err = REG_ESPACE; - parse_bracket_exp_free_return: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - return NULL; -} - -/* Parse an element in the bracket expression. */ - -static reg_errcode_t -parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token, int token_len, re_dfa_t *dfa, - reg_syntax_t syntax, bool accept_hyphen) -{ -#ifdef RE_ENABLE_I18N - int cur_char_size; - cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); - if (cur_char_size > 1) - { - elem->type = MB_CHAR; - elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); - re_string_skip_bytes (regexp, cur_char_size); - return REG_NOERROR; - } -#endif /* RE_ENABLE_I18N */ - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS - || token->type == OP_OPEN_EQUIV_CLASS) - return parse_bracket_symbol (elem, regexp, token); - if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) - { - /* A '-' must only appear as anything but a range indicator before - the closing bracket. Everything else is an error. */ - re_token_t token2; - (void) peek_token_bracket (&token2, regexp, syntax); - if (token2.type != OP_CLOSE_BRACKET) - /* The actual error value is not standardized since this whole - case is undefined. But ERANGE makes good sense. */ - return REG_ERANGE; - } - elem->type = SB_CHAR; - elem->opr.ch = token->opr.c; - return REG_NOERROR; -} - -/* Parse a bracket symbol in the bracket expression. Bracket symbols are - such as [::], [..], and - [==]. */ - -static reg_errcode_t -parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token) -{ - unsigned char ch, delim = token->opr.c; - int i = 0; - if (re_string_eoi(regexp)) - return REG_EBRACK; - for (;; ++i) - { - if (i >= BRACKET_NAME_BUF_SIZE) - return REG_EBRACK; - if (token->type == OP_OPEN_CHAR_CLASS) - ch = re_string_fetch_byte_case (regexp); - else - ch = re_string_fetch_byte (regexp); - if (re_string_eoi(regexp)) - return REG_EBRACK; - if (ch == delim && re_string_peek_byte (regexp, 0) == ']') - break; - elem->opr.name[i] = ch; - } - re_string_skip_bytes (regexp, 1); - elem->opr.name[i] = '\0'; - switch (token->type) - { - case OP_OPEN_COLL_ELEM: - elem->type = COLL_SYM; - break; - case OP_OPEN_EQUIV_CLASS: - elem->type = EQUIV_CLASS; - break; - case OP_OPEN_CHAR_CLASS: - elem->type = CHAR_CLASS; - break; - default: - break; - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the equivalence class which is represented by NAME. - The result are written to MBCSET and SBCSET. - EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, - Idx *equiv_class_alloc, const unsigned char *name) -#else /* not RE_ENABLE_I18N */ -build_equiv_class (bitset_t sbcset, const unsigned char *name) -#endif /* not RE_ENABLE_I18N */ -{ -#ifdef _LIBC - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - const int32_t *table, *indirect; - const unsigned char *weights, *extra, *cp; - unsigned char char_buf[2]; - int32_t idx1, idx2; - unsigned int ch; - size_t len; - /* This #include defines a local function! */ -# include - /* Calculate the index for equivalence class. */ - cp = name; - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - idx1 = findidx (&cp); - if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) - /* This isn't a valid character. */ - return REG_ECOLLATE; - - /* Build single byte matcing table for this equivalence class. */ - char_buf[1] = (unsigned char) '\0'; - len = weights[idx1]; - for (ch = 0; ch < SBC_MAX; ++ch) - { - char_buf[0] = ch; - cp = char_buf; - idx2 = findidx (&cp); -/* - idx2 = table[ch]; -*/ - if (idx2 == 0) - /* This isn't a valid character. */ - continue; - if (len == weights[idx2]) - { - int cnt = 0; - while (cnt <= len && - weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) - ++cnt; - - if (cnt > len) - bitset_set (sbcset, ch); - } - } - /* Check whether the array has enough space. */ - if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nequiv_classes is 0. */ - Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; - /* Use realloc since the array is NULL if *alloc == 0. */ - int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, - int32_t, - new_equiv_class_alloc); - if (BE (new_equiv_classes == NULL, 0)) - return REG_ESPACE; - mbcset->equiv_classes = new_equiv_classes; - *equiv_class_alloc = new_equiv_class_alloc; - } - mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; - } - else -#endif /* _LIBC */ - { - if (BE (strlen ((const char *) name) != 1, 0)) - return REG_ECOLLATE; - bitset_set (sbcset, *name); - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the character class which is represented by NAME. - The result are written to MBCSET and SBCSET. - CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - re_charset_t *mbcset, Idx *char_class_alloc, - const unsigned char *class_name, reg_syntax_t syntax) -#else /* not RE_ENABLE_I18N */ -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const unsigned char *class_name, reg_syntax_t syntax) -#endif /* not RE_ENABLE_I18N */ -{ - int i; - const char *name = (const char *) class_name; - - /* In case of REG_ICASE "upper" and "lower" match the both of - upper and lower cases. */ - if ((syntax & RE_ICASE) - && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) - name = "alpha"; - -#ifdef RE_ENABLE_I18N - /* Check the space of the arrays. */ - if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nchar_classes is 0. */ - Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, - new_char_class_alloc); - if (BE (new_char_classes == NULL, 0)) - return REG_ESPACE; - mbcset->char_classes = new_char_classes; - *char_class_alloc = new_char_class_alloc; - } - mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); -#endif /* RE_ENABLE_I18N */ - -#define BUILD_CHARCLASS_LOOP(ctype_func) \ - do { \ - if (BE (trans != NULL, 0)) \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, trans[i]); \ - } \ - else \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, i); \ - } \ - } while (0) - - if (strcmp (name, "alnum") == 0) - BUILD_CHARCLASS_LOOP (isalnum); - else if (strcmp (name, "cntrl") == 0) - BUILD_CHARCLASS_LOOP (iscntrl); - else if (strcmp (name, "lower") == 0) - BUILD_CHARCLASS_LOOP (islower); - else if (strcmp (name, "space") == 0) - BUILD_CHARCLASS_LOOP (isspace); - else if (strcmp (name, "alpha") == 0) - BUILD_CHARCLASS_LOOP (isalpha); - else if (strcmp (name, "digit") == 0) - BUILD_CHARCLASS_LOOP (isdigit); - else if (strcmp (name, "print") == 0) - BUILD_CHARCLASS_LOOP (isprint); - else if (strcmp (name, "upper") == 0) - BUILD_CHARCLASS_LOOP (isupper); - else if (strcmp (name, "blank") == 0) - BUILD_CHARCLASS_LOOP (isblank); - else if (strcmp (name, "graph") == 0) - BUILD_CHARCLASS_LOOP (isgraph); - else if (strcmp (name, "punct") == 0) - BUILD_CHARCLASS_LOOP (ispunct); - else if (strcmp (name, "xdigit") == 0) - BUILD_CHARCLASS_LOOP (isxdigit); - else - return REG_ECTYPE; - - return REG_NOERROR; -} - -static bin_tree_t * -build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, bool non_match, - reg_errcode_t *err) -{ - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - Idx alloc = 0; -#endif /* not RE_ENABLE_I18N */ - reg_errcode_t ret; - re_token_t br_token; - bin_tree_t *tree; - - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ - -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else /* not RE_ENABLE_I18N */ - if (BE (sbcset == NULL, 0)) -#endif /* not RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - if (non_match) - { -#ifdef RE_ENABLE_I18N - /* - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set(cset->sbcset, '\0'); - */ - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - } - - /* We don't care the syntax in this case. */ - ret = build_charclass (trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &alloc, -#endif /* RE_ENABLE_I18N */ - class_name, 0); - - if (BE (ret != REG_NOERROR, 0)) - { - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = ret; - return NULL; - } - /* \w match '_' also. */ - for (; *extra; extra++) - bitset_set (sbcset, *extra); - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); -#endif - - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (tree == NULL, 0)) - goto build_word_op_espace; - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - bin_tree_t *mbc_tree; - /* Build a tree for complex bracket. */ - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - dfa->has_mb_node = 1; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto build_word_op_espace; - /* Then join them by ALT node. */ - tree = create_tree (dfa, tree, mbc_tree, OP_ALT); - if (BE (mbc_tree != NULL, 1)) - return tree; - } - else - { - free_charset (mbcset); - return tree; - } -#else /* not RE_ENABLE_I18N */ - return tree; -#endif /* not RE_ENABLE_I18N */ - - build_word_op_espace: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = REG_ESPACE; - return NULL; -} - -/* This is intended for the expressions like "a{1,3}". - Fetch a number from `input', and return the number. - Return REG_MISSING if the number field is empty like "{,1}". - Return REG_ERROR if an error occurred. */ - -static Idx -fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -{ - Idx num = REG_MISSING; - unsigned char c; - while (1) - { - fetch_token (token, input, syntax); - c = token->opr.c; - if (BE (token->type == END_OF_RE, 0)) - return REG_ERROR; - if (token->type == OP_CLOSE_DUP_NUM || c == ',') - break; - num = ((token->type != CHARACTER || c < '0' || '9' < c - || num == REG_ERROR) - ? REG_ERROR - : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0')); - num = (num > RE_DUP_MAX) ? REG_ERROR : num; - } - return num; -} - -#ifdef RE_ENABLE_I18N -static void -free_charset (re_charset_t *cset) -{ - re_free (cset->mbchars); -# ifdef _LIBC - re_free (cset->coll_syms); - re_free (cset->equiv_classes); - re_free (cset->range_starts); - re_free (cset->range_ends); -# endif - re_free (cset->char_classes); - re_free (cset); -} -#endif /* RE_ENABLE_I18N */ - -/* Functions for binary tree operation. */ - -/* Create a tree node. */ - -static bin_tree_t * -create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - re_token_type_t type) -{ - re_token_t t; - t.type = type; - return create_token_tree (dfa, left, right, &t); -} - -static bin_tree_t * -create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - const re_token_t *token) -{ - bin_tree_t *tree; - if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) - { - bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); - - if (storage == NULL) - return NULL; - storage->next = dfa->str_tree_storage; - dfa->str_tree_storage = storage; - dfa->str_tree_storage_idx = 0; - } - tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; - - tree->parent = NULL; - tree->left = left; - tree->right = right; - tree->token = *token; - tree->token.duplicated = 0; - tree->token.opt_subexp = 0; - tree->first = NULL; - tree->next = NULL; - tree->node_idx = REG_MISSING; - - if (left != NULL) - left->parent = tree; - if (right != NULL) - right->parent = tree; - return tree; -} - -/* Mark the tree SRC as an optional subexpression. - To be called from preorder or postorder. */ - -static reg_errcode_t -mark_opt_subexp (void *extra, bin_tree_t *node) -{ - Idx idx = (Idx) (long) extra; - if (node->token.type == SUBEXP && node->token.opr.idx == idx) - node->token.opt_subexp = 1; - - return REG_NOERROR; -} - -/* Free the allocated memory inside NODE. */ - -static void -free_token (re_token_t *node) -{ -#ifdef RE_ENABLE_I18N - if (node->type == COMPLEX_BRACKET && node->duplicated == 0) - free_charset (node->opr.mbcset); - else -#endif /* RE_ENABLE_I18N */ - if (node->type == SIMPLE_BRACKET && node->duplicated == 0) - re_free (node->opr.sbcset); -} - -/* Worker function for tree walking. Free the allocated memory inside NODE - and its children. */ - -static reg_errcode_t -free_tree (void *extra, bin_tree_t *node) -{ - free_token (&node->token); - return REG_NOERROR; -} - - -/* Duplicate the node SRC, and return new node. This is a preorder - visit similar to the one implemented by the generic visitor, but - we need more infrastructure to maintain two parallel trees --- so, - it's easier to duplicate. */ - -static bin_tree_t * -duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) -{ - const bin_tree_t *node; - bin_tree_t *dup_root; - bin_tree_t **p_new = &dup_root, *dup_node = root->parent; - - for (node = root; ; ) - { - /* Create a new tree and link it back to the current parent. */ - *p_new = create_token_tree (dfa, NULL, NULL, &node->token); - if (*p_new == NULL) - return NULL; - (*p_new)->parent = dup_node; - (*p_new)->token.duplicated = 1; - dup_node = *p_new; - - /* Go to the left node, or up and to the right. */ - if (node->left) - { - node = node->left; - p_new = &dup_node->left; - } - else - { - const bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - dup_node = dup_node->parent; - if (!node) - return dup_root; - } - node = node->right; - p_new = &dup_node->right; - } - } -} diff --git a/src/bin/m4/lib/regex.c b/src/bin/m4/lib/regex.c deleted file mode 100644 index d4eb726b29..0000000000 --- a/src/bin/m4/lib/regex.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Make sure noone compiles this code with a C++ compiler. */ -#if defined __cplusplus && defined _LIBC -# error "This is C code, use a C compiler" -#endif - -#ifdef _LIBC -/* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ - __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ - __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ - __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ - __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ - __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ - __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ - __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) - -# include "../locale/localeinfo.h" -#endif - -/* On some systems, limits.h sets RE_DUP_MAX to a lower value than - GNU regex allows. Include it before , which correctly - #undefs RE_DUP_MAX and sets it to the right value. */ -#include - -#include -#include "regex_internal.h" - -#include "regex_internal.c" -#include "regcomp.c" -#include "regexec.c" - -/* Binary backward compatibility. */ -#if _LIBC -# include -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) -link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") -int re_max_failures = 2000; -# endif -#endif diff --git a/src/bin/m4/lib/regex.h b/src/bin/m4/lib/regex.h deleted file mode 100644 index e8748e195b..0000000000 --- a/src/bin/m4/lib/regex.h +++ /dev/null @@ -1,668 +0,0 @@ -/* Definitions for data structures and routines for the regular - expression library. - Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _REGEX_H -#define _REGEX_H 1 - -#include - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Define __USE_GNU_REGEX to declare GNU extensions that violate the - POSIX name space rules. */ -#undef __USE_GNU_REGEX -#if (defined _GNU_SOURCE \ - || (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \ - && !defined _XOPEN_SOURCE)) -# define __USE_GNU_REGEX 1 -#endif - -#ifdef _REGEX_LARGE_OFFSETS - -/* Use types and values that are wide enough to represent signed and - unsigned byte offsets in memory. This currently works only when - the regex code is used outside of the GNU C library; it is not yet - supported within glibc itself, and glibc users should not define - _REGEX_LARGE_OFFSETS. */ - -/* The type of the offset of a byte within a string. - For historical reasons POSIX 1003.1-2004 requires that regoff_t be - at least as wide as off_t. However, many common POSIX platforms set - regoff_t to the more-sensible ssize_t and the Open Group has - signalled its intention to change the requirement to be that - regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN - 60 (2005-08-25). We don't know of any hosts where ssize_t or - ptrdiff_t is wider than ssize_t, so ssize_t is safe. */ -typedef ssize_t regoff_t; - -/* The type of nonnegative object indexes. Traditionally, GNU regex - uses 'int' for these. Code that uses __re_idx_t should work - regardless of whether the type is signed. */ -typedef size_t __re_idx_t; - -/* The type of object sizes. */ -typedef size_t __re_size_t; - -/* The type of object sizes, in places where the traditional code - uses unsigned long int. */ -typedef size_t __re_long_size_t; - -#else - -/* Use types that are binary-compatible with the traditional GNU regex - implementation, which mishandles strings longer than INT_MAX. */ - -typedef int regoff_t; -typedef int __re_idx_t; -typedef unsigned int __re_size_t; -typedef unsigned long int __re_long_size_t; - -#endif - -/* The following two types have to be signed and unsigned integer type - wide enough to hold a value of a pointer. For most ANSI compilers - ptrdiff_t and size_t should be likely OK. Still size of these two - types is 2 for Microsoft C. Ugh... */ -typedef long int s_reg_t; -typedef unsigned long int active_reg_t; - -/* The following bits are used to determine the regexp syntax we - recognize. The set/not-set meanings are chosen so that Emacs syntax - remains the value 0. The bits are given in alphabetical order, and - the definitions shifted by one from the previous bit; thus, when we - add or remove a bit, only one other definition need change. */ -typedef unsigned long int reg_syntax_t; - -#ifdef __USE_GNU_REGEX - -/* If this bit is not set, then \ inside a bracket expression is literal. - If set, then such a \ quotes the following character. */ -# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) - -/* If this bit is not set, then + and ? are operators, and \+ and \? are - literals. - If set, then \+ and \? are operators and + and ? are literals. */ -# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) - -/* If this bit is set, then character classes are supported. They are: - [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], - [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. - If not set, then character classes are not supported. */ -# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) - -/* If this bit is set, then ^ and $ are always anchors (outside bracket - expressions, of course). - If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. - - This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because - POSIX draft 11.2 says that * etc. in leading positions is undefined. - We already implemented a previous draft which made those constructs - invalid, though, so we haven't changed the code back. */ -# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) - -/* If this bit is set, then special characters are always special - regardless of where they are in the pattern. - If this bit is not set, then special characters are special only in - some contexts; otherwise they are ordinary. Specifically, - * + ? and intervals are only special when not after the beginning, - open-group, or alternation operator. */ -# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) - -/* If this bit is set, then *, +, ?, and { cannot be first in an re or - immediately after an alternation or begin-group operator. */ -# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) - -/* If this bit is set, then . matches newline. - If not set, then it doesn't. */ -# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) - -/* If this bit is set, then . doesn't match NUL. - If not set, then it does. */ -# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) - -/* If this bit is set, nonmatching lists [^...] do not match newline. - If not set, they do. */ -# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) - -/* If this bit is set, either \{...\} or {...} defines an - interval, depending on RE_NO_BK_BRACES. - If not set, \{, \}, {, and } are literals. */ -# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) - -/* If this bit is set, +, ? and | aren't recognized as operators. - If not set, they are. */ -# define RE_LIMITED_OPS (RE_INTERVALS << 1) - -/* If this bit is set, newline is an alternation operator. - If not set, newline is literal. */ -# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) - -/* If this bit is set, then `{...}' defines an interval, and \{ and \} - are literals. - If not set, then `\{...\}' defines an interval. */ -# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) - -/* If this bit is set, (...) defines a group, and \( and \) are literals. - If not set, \(...\) defines a group, and ( and ) are literals. */ -# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) - -/* If this bit is set, then \ matches . - If not set, then \ is a back-reference. */ -# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) - -/* If this bit is set, then | is an alternation operator, and \| is literal. - If not set, then \| is an alternation operator, and | is literal. */ -# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) - -/* If this bit is set, then an ending range point collating higher - than the starting range point, as in [z-a], is invalid. - If not set, then when ending range point collates higher than the - starting range point, the range is ignored. */ -# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) - -/* If this bit is set, then an unmatched ) is ordinary. - If not set, then an unmatched ) is invalid. */ -# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) - -/* If this bit is set, succeed as soon as we match the whole pattern, - without further backtracking. */ -# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) - -/* If this bit is set, do not process the GNU regex operators. - If not set, then the GNU regex operators are recognized. */ -# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) - -/* If this bit is set, turn on internal regex debugging. - If not set, and debugging was on, turn it off. - This only works if regex.c is compiled -DDEBUG. - We define this bit always, so that all that's needed to turn on - debugging is to recompile regex.c; the calling code can always have - this bit set, and it won't affect anything in the normal case. */ -# define RE_DEBUG (RE_NO_GNU_OPS << 1) - -/* If this bit is set, a syntactically invalid interval is treated as - a string of ordinary characters. For example, the ERE 'a{1' is - treated as 'a\{1'. */ -# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) - -/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only - for ^, because it is difficult to scan the regex backwards to find - whether ^ should be special. */ -# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) - -/* If this bit is set, then \{ cannot be first in an bre or - immediately after an alternation or begin-group operator. */ -# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) - -/* If this bit is set, then no_sub will be set to 1 during - re_compile_pattern. */ -# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) - -#endif /* defined __USE_GNU_REGEX */ - -/* This global variable defines the particular regexp syntax to use (for - some interfaces). When a regexp is compiled, the syntax used is - stored in the pattern buffer, so changing this does not affect - already-compiled regexps. */ -extern reg_syntax_t re_syntax_options; - -#ifdef __USE_GNU_REGEX -/* Define combinations of the above bits for the standard possibilities. - (The [[[ comments delimit what gets put into the Texinfo file, so - don't delete them!) */ -/* [[[begin syntaxes]]] */ -# define RE_SYNTAX_EMACS 0 - -# define RE_SYNTAX_AWK \ - (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ - | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ - | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) - -# define RE_SYNTAX_POSIX_AWK \ - (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GREP \ - (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ - | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ - | RE_NEWLINE_ALT) - -# define RE_SYNTAX_EGREP \ - (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ - | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ - | RE_NO_BK_VBAR) - -# define RE_SYNTAX_POSIX_EGREP \ - (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ - | RE_INVALID_INTERVAL_ORD) - -/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ -# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC - -# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC - -/* Syntax bits common to both basic and extended POSIX regex syntax. */ -# define _RE_SYNTAX_POSIX_COMMON \ - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -# define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) - -/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this - isn't minimal, since other operators, such as \`, aren't disabled. */ -# define RE_SYNTAX_POSIX_MINIMAL_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) - -# define RE_SYNTAX_POSIX_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ - | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) - -/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is - removed and RE_NO_BK_REFS is added. */ -# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) -/* [[[end syntaxes]]] */ - -#endif /* defined __USE_GNU_REGEX */ - -#ifdef __USE_GNU_REGEX - -/* Maximum number of duplicates an interval can allow. POSIX-conforming - systems might define this in , but we want our - value, so remove any previous define. */ -# ifdef RE_DUP_MAX -# undef RE_DUP_MAX -# endif - -/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored - the counter as a 2-byte signed integer. This is no longer true, so - RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to - ((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined. - However, there would be a huge performance problem if someone - actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains - its historical value. */ -# define RE_DUP_MAX (0x7fff) - -#endif /* defined __USE_GNU_REGEX */ - - -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ - -/* If this bit is set, then use extended regular expression syntax. - If not set, then use basic regular expression syntax. */ -#define REG_EXTENDED 1 - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define REG_ICASE (1 << 1) - -/* If this bit is set, then anchors do not match at newline - characters in the string. - If not set, then anchors do match at newlines. */ -#define REG_NEWLINE (1 << 2) - -/* If this bit is set, then report only success or fail in regexec. - If not set, then returns differ between not matching and errors. */ -#define REG_NOSUB (1 << 3) - - -/* POSIX `eflags' bits (i.e., information for regexec). */ - -/* If this bit is set, then the beginning-of-line operator doesn't match - the beginning of the string (presumably because it's not the - beginning of a line). - If not set, then the beginning-of-line operator does match the - beginning of the string. */ -#define REG_NOTBOL 1 - -/* Like REG_NOTBOL, except for the end-of-line. */ -#define REG_NOTEOL (1 << 1) - -/* Use PMATCH[0] to delimit the start and end of the search in the - buffer. */ -#define REG_STARTEND (1 << 2) - - -/* If any error codes are removed, changed, or added, update the - `__re_error_msgid' table in regcomp.c. */ - -typedef enum -{ - _REG_ENOSYS = -1, /* This will never happen for this implementation. */ - _REG_NOERROR = 0, /* Success. */ - _REG_NOMATCH, /* Didn't find a match (for regexec). */ - - /* POSIX regcomp return error codes. (In the order listed in the - standard.) */ - _REG_BADPAT, /* Invalid pattern. */ - _REG_ECOLLATE, /* Invalid collating element. */ - _REG_ECTYPE, /* Invalid character class name. */ - _REG_EESCAPE, /* Trailing backslash. */ - _REG_ESUBREG, /* Invalid back reference. */ - _REG_EBRACK, /* Unmatched left bracket. */ - _REG_EPAREN, /* Parenthesis imbalance. */ - _REG_EBRACE, /* Unmatched \{. */ - _REG_BADBR, /* Invalid contents of \{\}. */ - _REG_ERANGE, /* Invalid range end. */ - _REG_ESPACE, /* Ran out of memory. */ - _REG_BADRPT, /* No preceding re for repetition op. */ - - /* Error codes we've added. */ - _REG_EEND, /* Premature end. */ - _REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ - _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ -} reg_errcode_t; - -#ifdef _XOPEN_SOURCE -# define REG_ENOSYS _REG_ENOSYS -#endif -#define REG_NOERROR _REG_NOERROR -#define REG_NOMATCH _REG_NOMATCH -#define REG_BADPAT _REG_BADPAT -#define REG_ECOLLATE _REG_ECOLLATE -#define REG_ECTYPE _REG_ECTYPE -#define REG_EESCAPE _REG_EESCAPE -#define REG_ESUBREG _REG_ESUBREG -#define REG_EBRACK _REG_EBRACK -#define REG_EPAREN _REG_EPAREN -#define REG_EBRACE _REG_EBRACE -#define REG_BADBR _REG_BADBR -#define REG_ERANGE _REG_ERANGE -#define REG_ESPACE _REG_ESPACE -#define REG_BADRPT _REG_BADRPT -#define REG_EEND _REG_EEND -#define REG_ESIZE _REG_ESIZE -#define REG_ERPAREN _REG_ERPAREN - -/* struct re_pattern_buffer normally uses member names like `buffer' - that POSIX does not allow. In POSIX mode these members have names - with leading `re_' (e.g., `re_buffer'). */ -#ifdef __USE_GNU_REGEX -# define _REG_RE_NAME(id) id -# define _REG_RM_NAME(id) id -#else -# define _REG_RE_NAME(id) re_##id -# define _REG_RM_NAME(id) rm_##id -#endif - -/* The user can specify the type of the re_translate member by - defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned - char *. This pollutes the POSIX name space, so in POSIX mode just - use unsigned char *. */ -#ifdef __USE_GNU_REGEX -# ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE unsigned char * -# endif -# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE -#else -# define REG_TRANSLATE_TYPE unsigned char * -#endif - -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ - -struct re_pattern_buffer -{ - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are sometimes used as - array indexes. */ - unsigned char *_REG_RE_NAME (buffer); - - /* Number of bytes to which `buffer' points. */ - __re_long_size_t _REG_RE_NAME (allocated); - - /* Number of bytes actually used in `buffer'. */ - __re_long_size_t _REG_RE_NAME (used); - - /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t _REG_RE_NAME (syntax); - - /* Pointer to a fastmap, if any, otherwise zero. re_search uses the - fastmap, if there is one, to skip over impossible starting points - for matches. */ - char *_REG_RE_NAME (fastmap); - - /* Either a translate table to apply to all characters before - comparing them, or zero for no translation. The translation is - applied to a pattern when it is compiled and to a string when it - is matched. */ - REG_TRANSLATE_TYPE _REG_RE_NAME (translate); - - /* Number of subexpressions found by the compiler. */ - size_t re_nsub; - - /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see whether or - not we should use the fastmap, so we don't set this absolutely - perfectly; see `re_compile_fastmap' (the `duplicate' case). */ - unsigned int _REG_RE_NAME (can_be_null) : 1; - - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. - If REGS_REALLOCATE, reallocate space if necessary. - If REGS_FIXED, use what's there. */ -#ifdef __USE_GNU_REGEX -# define REGS_UNALLOCATED 0 -# define REGS_REALLOCATE 1 -# define REGS_FIXED 2 -#endif - unsigned int _REG_RE_NAME (regs_allocated) : 2; - - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ - unsigned int _REG_RE_NAME (fastmap_accurate) : 1; - - /* If set, `re_match_2' does not return information about - subexpressions. */ - unsigned int _REG_RE_NAME (no_sub) : 1; - - /* If set, a beginning-of-line anchor doesn't match at the beginning - of the string. */ - unsigned int _REG_RE_NAME (not_bol) : 1; - - /* Similarly for an end-of-line anchor. */ - unsigned int _REG_RE_NAME (not_eol) : 1; - - /* If true, an anchor at a newline matches. */ - unsigned int _REG_RE_NAME (newline_anchor) : 1; - -/* [[[end pattern_buffer]]] */ -}; - -typedef struct re_pattern_buffer regex_t; - -/* This is the structure we store register match data in. See - regex.texinfo for a full description of what registers match. */ -struct re_registers -{ - __re_size_t _REG_RM_NAME (num_regs); - regoff_t *_REG_RM_NAME (start); - regoff_t *_REG_RM_NAME (end); -}; - - -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#if !defined RE_NREGS && defined __USE_GNU_REGEX -# define RE_NREGS 30 -#endif - - -/* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a - structure of arrays. */ -typedef struct -{ - regoff_t rm_so; /* Byte offset from string's start to substring's start. */ - regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -} regmatch_t; - -/* Declarations for routines. */ - -/* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); - -/* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ -extern const char *re_compile_pattern (const char *__pattern, size_t __length, - struct re_pattern_buffer *__buffer); - - -/* Compile a fastmap for the compiled pattern in BUFFER; used to - accelerate searches. Return 0 if successful and -2 if was an - internal error. */ -extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); - - -/* Search in the string STRING (with length LENGTH) for the pattern - compiled into BUFFER. Start searching at position START, for RANGE - characters. Return the starting position of the match, -1 for no - match, or -2 for an internal error. Also return register - information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern regoff_t re_search (struct re_pattern_buffer *__buffer, - const char *__string, __re_idx_t __length, - __re_idx_t __start, regoff_t __range, - struct re_registers *__regs); - - -/* Like `re_search', but search in the concatenation of STRING1 and - STRING2. Also, stop searching at index START + STOP. */ -extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, - const char *__string1, __re_idx_t __length1, - const char *__string2, __re_idx_t __length2, - __re_idx_t __start, regoff_t __range, - struct re_registers *__regs, - __re_idx_t __stop); - - -/* Like `re_search', but return how many characters in STRING the regexp - in BUFFER matched, starting at position START. */ -extern regoff_t re_match (struct re_pattern_buffer *__buffer, - const char *__string, __re_idx_t __length, - __re_idx_t __start, struct re_registers *__regs); - - -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ -extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, - const char *__string1, __re_idx_t __length1, - const char *__string2, __re_idx_t __length2, - __re_idx_t __start, struct re_registers *__regs, - __re_idx_t __stop); - - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using BUFFER and REGS will use this memory - for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least `NUM_REGS * sizeof - (regoff_t)' bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ -extern void re_set_registers (struct re_pattern_buffer *__buffer, - struct re_registers *__regs, - __re_size_t __num_regs, - regoff_t *__starts, regoff_t *__ends); - -#if defined _REGEX_RE_COMP || defined _LIBC -# ifndef _CRAY -/* 4.2 bsd compatibility. */ -extern char *re_comp (const char *); -extern int re_exec (const char *); -# endif -#endif - -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". */ -#ifndef __restrict -# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) -# if defined restrict || 199901L <= __STDC_VERSION__ -# define __restrict restrict -# else -# define __restrict -# endif -# endif -#endif -/* gcc 3.1 and up support the [restrict] syntax. */ -#ifndef __restrict_arr -# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \ - && !defined __GNUG__ -# define __restrict_arr __restrict -# else -# define __restrict_arr -# endif -#endif - -/* POSIX compatibility. */ -extern int regcomp (regex_t *__restrict __preg, - const char *__restrict __pattern, - int __cflags); - -extern int regexec (const regex_t *__restrict __preg, - const char *__restrict __string, size_t __nmatch, - regmatch_t __pmatch[__restrict_arr], - int __eflags); - -extern size_t regerror (int __errcode, const regex_t *__restrict __preg, - char *__restrict __errbuf, size_t __errbuf_size); - -extern void regfree (regex_t *__preg); - - -#ifdef __cplusplus -} -#endif /* C++ */ - -#endif /* regex.h */ diff --git a/src/bin/m4/lib/regex_internal.c b/src/bin/m4/lib/regex_internal.c deleted file mode 100644 index 78e16f3301..0000000000 --- a/src/bin/m4/lib/regex_internal.c +++ /dev/null @@ -1,1742 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static void re_string_construct_common (const char *str, Idx len, - re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) internal_function; -static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - re_hashval_t hash) internal_function; -static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - unsigned int context, - re_hashval_t hash) internal_function; - -/* Functions for string operation. */ - -/* This function allocate the buffers. It is necessary to call - re_string_reconstruct before using the object. */ - -static reg_errcode_t -internal_function -re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - Idx init_buf_len; - - /* Ensure at least one character fits into the buffers. */ - if (init_len < dfa->mb_cur_max) - init_len = dfa->mb_cur_max; - init_buf_len = (len + 1 < init_len) ? len + 1: init_len; - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - ret = re_string_realloc_buffers (pstr, init_buf_len); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - pstr->word_char = dfa->word_char; - pstr->word_ops_used = dfa->word_ops_used; - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; - pstr->valid_raw_len = pstr->valid_len; - return REG_NOERROR; -} - -/* This function allocate the buffers, and initialize them. */ - -static reg_errcode_t -internal_function -re_string_construct (re_string_t *pstr, const char *str, Idx len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - memset (pstr, '\0', sizeof (re_string_t)); - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - if (len > 0) - { - ret = re_string_realloc_buffers (pstr, len + 1); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - - if (icase) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - if (pstr->valid_raw_len >= len) - break; - if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) - break; - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (trans != NULL) - re_string_translate_buffer (pstr); - else - { - pstr->valid_len = pstr->bufs_len; - pstr->valid_raw_len = pstr->bufs_len; - } - } - } - - return REG_NOERROR; -} - -/* Helper functions for re_string_allocate, and re_string_construct. */ - -static reg_errcode_t -internal_function -re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) -{ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - wint_t *new_wcs; - - /* Avoid overflow. */ - size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (BE (SIZE_MAX / max_object_size < new_buf_len, 0)) - return REG_ESPACE; - - new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); - if (BE (new_wcs == NULL, 0)) - return REG_ESPACE; - pstr->wcs = new_wcs; - if (pstr->offsets != NULL) - { - Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); - if (BE (new_offsets == NULL, 0)) - return REG_ESPACE; - pstr->offsets = new_offsets; - } - } -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - { - unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, - new_buf_len); - if (BE (new_mbs == NULL, 0)) - return REG_ESPACE; - pstr->mbs = new_mbs; - } - pstr->bufs_len = new_buf_len; - return REG_NOERROR; -} - - -static void -internal_function -re_string_construct_common (const char *str, Idx len, re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) -{ - pstr->raw_mbs = (const unsigned char *) str; - pstr->len = len; - pstr->raw_len = len; - pstr->trans = trans; - pstr->icase = icase; - pstr->mbs_allocated = (trans != NULL || icase); - pstr->mb_cur_max = dfa->mb_cur_max; - pstr->is_utf8 = dfa->is_utf8; - pstr->map_notascii = dfa->map_notascii; - pstr->stop = pstr->len; - pstr->raw_stop = pstr->stop; -} - -#ifdef RE_ENABLE_I18N - -/* Build wide character buffer PSTR->WCS. - If the byte sequence of the string are: - (0), (1), (0), (1), - Then wide character buffer will be: - , WEOF , , WEOF , - We use WEOF for padding, they indicate that the position isn't - a first byte of a multibyte character. - - Note that this function assumes PSTR->VALID_LEN elements are already - built and starts from PSTR->VALID_LEN. */ - -static void -internal_function -build_wcs_buffer (re_string_t *pstr) -{ -#ifdef _LIBC - unsigned char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - unsigned char buf[64]; -#endif - mbstate_t prev_st; - Idx byte_idx, end_idx, remain_len; - size_t mbclen; - - /* Build the buffers from pstr->valid_len to either pstr->len or - pstr->bufs_len. */ - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - for (byte_idx = pstr->valid_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - /* Apply the translation if we need. */ - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; - buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; - mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a singlebyte character. */ - mbclen = 1; - wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - if (BE (pstr->trans != NULL, 0)) - wc = pstr->trans[wc]; - pstr->cur_state = prev_st; - } - - /* Write wide character and padding. */ - pstr->wcs[byte_idx++] = wc; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; -} - -/* Build wide character buffer PSTR->WCS like build_wcs_buffer, - but for REG_ICASE. */ - -static reg_errcode_t -internal_function -build_wcs_upper_buffer (re_string_t *pstr) -{ - mbstate_t prev_st; - Idx src_idx, byte_idx, end_idx, remain_len; - size_t mbclen; -#ifdef _LIBC - char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - char buf[64]; -#endif - - byte_idx = pstr->valid_len; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - /* The following optimization assumes that ASCII characters can be - mapped to wide characters with a simple cast. */ - if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) - { - while (byte_idx < end_idx) - { - wchar_t wc; - - if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) - && mbsinit (&pstr->cur_state)) - { - /* In case of a singlebyte character. */ - pstr->mbs[byte_idx] - = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); - /* The next step uses the assumption that wchar_t is encoded - ASCII-safe: all ASCII values can be converted like this. */ - pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; - ++byte_idx; - continue; - } - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - mbclen = mbrtowc (&wc, - ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx - + byte_idx), remain_len, &pstr->cur_state); - if (BE (mbclen < (size_t) -2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb (buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else - { - src_idx = byte_idx; - goto offsets_needed; - } - } - else - memcpy (pstr->mbs + byte_idx, - pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - pstr->mbs[byte_idx] = ch; - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; - return REG_NOERROR; - } - else - for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - offsets_needed: - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; - buf[i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; - mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen < (size_t) -2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else if (mbcdlen != (size_t) -1) - { - size_t i; - - if (byte_idx + mbcdlen > pstr->bufs_len) - { - pstr->cur_state = prev_st; - break; - } - - if (pstr->offsets == NULL) - { - pstr->offsets = re_malloc (Idx, pstr->bufs_len); - - if (pstr->offsets == NULL) - return REG_ESPACE; - } - if (!pstr->offsets_needed) - { - for (i = 0; i < (size_t) byte_idx; ++i) - pstr->offsets[i] = i; - pstr->offsets_needed = 1; - } - - memcpy (pstr->mbs + byte_idx, buf, mbcdlen); - pstr->wcs[byte_idx] = wcu; - pstr->offsets[byte_idx] = src_idx; - for (i = 1; i < mbcdlen; ++i) - { - pstr->offsets[byte_idx + i] - = src_idx + (i < mbclen ? i : mbclen - 1); - pstr->wcs[byte_idx + i] = WEOF; - } - pstr->len += mbcdlen - mbclen; - if (pstr->raw_stop > src_idx) - pstr->stop += mbcdlen - mbclen; - end_idx = (pstr->bufs_len > pstr->len) - ? pstr->len : pstr->bufs_len; - byte_idx += mbcdlen; - src_idx += mbclen; - continue; - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - - if (BE (pstr->offsets_needed != 0, 0)) - { - size_t i; - for (i = 0; i < mbclen; ++i) - pstr->offsets[byte_idx + i] = src_idx + i; - } - src_idx += mbclen; - - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; - - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans [ch]; - pstr->mbs[byte_idx] = ch; - - if (BE (pstr->offsets_needed != 0, 0)) - pstr->offsets[byte_idx] = src_idx; - ++src_idx; - - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = src_idx; - return REG_NOERROR; -} - -/* Skip characters until the index becomes greater than NEW_RAW_IDX. - Return the index. */ - -static Idx -internal_function -re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) -{ - mbstate_t prev_st; - Idx rawbuf_idx; - size_t mbclen; - wint_t wc = WEOF; - - /* Skip the characters which are not necessary to check. */ - for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; - rawbuf_idx < new_raw_idx;) - { - wchar_t wc2; - Idx remain_len; - remain_len = pstr->len - rawbuf_idx; - prev_st = pstr->cur_state; - mbclen = mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, - remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a single byte character. */ - if (mbclen == 0 || remain_len == 0) - wc = L'\0'; - else - wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); - mbclen = 1; - pstr->cur_state = prev_st; - } - else - wc = wc2; - /* Then proceed the next character. */ - rawbuf_idx += mbclen; - } - *last_wc = wc; - return rawbuf_idx; -} -#endif /* RE_ENABLE_I18N */ - -/* Build the buffer PSTR->MBS, and apply the translation if we need. - This function is used in case of REG_ICASE. */ - -static void -internal_function -build_upper_buffer (re_string_t *pstr) -{ - Idx char_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans[ch]; - if (islower (ch)) - pstr->mbs[char_idx] = toupper (ch); - else - pstr->mbs[char_idx] = ch; - } - pstr->valid_len = char_idx; - pstr->valid_raw_len = char_idx; -} - -/* Apply TRANS to the buffer in PSTR. */ - -static void -internal_function -re_string_translate_buffer (re_string_t *pstr) -{ - Idx buf_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; - pstr->mbs[buf_idx] = pstr->trans[ch]; - } - - pstr->valid_len = buf_idx; - pstr->valid_raw_len = buf_idx; -} - -/* This function re-construct the buffers. - Concretely, convert to wide character in case of pstr->mb_cur_max > 1, - convert to upper case in case of REG_ICASE, apply translation. */ - -static reg_errcode_t -internal_function -re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) -{ - Idx offset; - - if (BE (pstr->raw_mbs_idx <= idx, 0)) - offset = idx - pstr->raw_mbs_idx; - else - { - /* Reset buffer. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); -#endif /* RE_ENABLE_I18N */ - pstr->len = pstr->raw_len; - pstr->stop = pstr->raw_stop; - pstr->valid_len = 0; - pstr->raw_mbs_idx = 0; - pstr->valid_raw_len = 0; - pstr->offsets_needed = 0; - pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (!pstr->mbs_allocated) - pstr->mbs = (unsigned char *) pstr->raw_mbs; - offset = idx; - } - - if (BE (offset != 0, 1)) - { - /* Should the already checked characters be kept? */ - if (BE (offset < pstr->valid_raw_len, 1)) - { - /* Yes, move them to the front of the buffer. */ -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - Idx low = 0, high = pstr->valid_len, mid; - do - { - mid = (high + low) / 2; - if (pstr->offsets[mid] > offset) - high = mid; - else if (pstr->offsets[mid] < offset) - low = mid + 1; - else - break; - } - while (low < high); - if (pstr->offsets[mid] < offset) - ++mid; - pstr->tip_context = re_string_context_at (pstr, mid - 1, - eflags); - /* This can be quite complicated, so handle specially - only the common and easy case where the character with - different length representation of lower and upper - case is present at or after offset. */ - if (pstr->valid_len > offset - && mid == offset && pstr->offsets[mid] == offset) - { - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; - for (low = 0; low < pstr->valid_len; low++) - pstr->offsets[low] = pstr->offsets[low + offset] - offset; - } - else - { - /* Otherwise, just find out how long the partial multibyte - character at offset is and fill it with WEOF/255. */ - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - while (mid > 0 && pstr->offsets[mid - 1] == offset) - --mid; - while (mid < pstr->valid_len) - if (pstr->wcs[mid] != WEOF) - break; - else - ++mid; - if (mid == pstr->valid_len) - pstr->valid_len = 0; - else - { - pstr->valid_len = pstr->offsets[mid] - offset; - if (pstr->valid_len) - { - for (low = 0; low < pstr->valid_len; ++low) - pstr->wcs[low] = WEOF; - memset (pstr->mbs, 255, pstr->valid_len); - } - } - pstr->valid_raw_len = pstr->valid_len; - } - } - else -#endif - { - pstr->tip_context = re_string_context_at (pstr, offset - 1, - eflags); -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - memmove (pstr->mbs, pstr->mbs + offset, - pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; -#if DEBUG - assert (pstr->valid_len > 0); -#endif - } - } - else - { - /* No, skip all characters until IDX. */ - Idx prev_valid_len = pstr->valid_len; - -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - } -#endif - pstr->valid_len = 0; -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - Idx wcs_idx; - wint_t wc = WEOF; - - if (pstr->is_utf8) - { - const unsigned char *raw, *p, *q, *end; - - /* Special case UTF-8. Multi-byte chars start with any - byte other than 0x80 - 0xbf. */ - raw = pstr->raw_mbs + pstr->raw_mbs_idx; - end = raw + (offset - pstr->mb_cur_max); - if (end < pstr->raw_mbs) - end = pstr->raw_mbs; - p = raw + offset - 1; -#ifdef _LIBC - /* We know the wchar_t encoding is UCS4, so for the simple - case, ASCII characters, skip the conversion step. */ - if (isascii (*p) && BE (pstr->trans == NULL, 1)) - { - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - /* pstr->valid_len = 0; */ - wc = (wchar_t) *p; - } - else -#endif - for (; p >= end; --p) - if ((*p & 0xc0) != 0x80) - { - mbstate_t cur_state; - wchar_t wc2; - Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; - size_t mbclen; - - q = p; - if (BE (pstr->trans != NULL, 0)) - { - int i = mlen < 6 ? mlen : 6; - while (--i >= 0) - buf[i] = pstr->trans[p[i]]; - q = buf; - } - /* XXX Don't use mbrtowc, we know which conversion - to use (UTF-8 -> UCS4). */ - memset (&cur_state, 0, sizeof (cur_state)); - mbclen = mbrtowc (&wc2, (const char *) p, mlen, - &cur_state); - if (raw + offset - p <= mbclen - && mbclen < (size_t) -2) - { - memset (&pstr->cur_state, '\0', - sizeof (mbstate_t)); - pstr->valid_len = mbclen - (raw + offset - p); - wc = wc2; - } - break; - } - } - - if (wc == WEOF) - pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; - if (wc == WEOF) - pstr->tip_context - = re_string_context_at (pstr, prev_valid_len - 1, eflags); - else - pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) - && IS_WIDE_WORD_CHAR (wc)) - ? CONTEXT_WORD - : ((IS_WIDE_NEWLINE (wc) - && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - if (BE (pstr->valid_len, 0)) - { - for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) - pstr->wcs[wcs_idx] = WEOF; - if (pstr->mbs_allocated) - memset (pstr->mbs, 255, pstr->valid_len); - } - pstr->valid_raw_len = pstr->valid_len; - } - else -#endif /* RE_ENABLE_I18N */ - { - int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; - pstr->valid_raw_len = 0; - if (pstr->trans) - c = pstr->trans[c]; - pstr->tip_context = (bitset_contain (pstr->word_char, c) - ? CONTEXT_WORD - : ((IS_NEWLINE (c) && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - } - } - if (!BE (pstr->mbs_allocated, 0)) - pstr->mbs += offset; - } - pstr->raw_mbs_idx = idx; - pstr->len -= offset; - pstr->stop -= offset; - - /* Then build the buffers. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - if (pstr->icase) - { - reg_errcode_t ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else - build_wcs_buffer (pstr); - } - else -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - { - if (pstr->icase) - build_upper_buffer (pstr); - else if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - else - pstr->valid_len = pstr->len; - - pstr->cur_idx = 0; - return REG_NOERROR; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_peek_byte_case (const re_string_t *pstr, Idx idx) -{ - int ch; - Idx off; - - /* Handle the common (easiest) cases first. */ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_peek_byte (pstr, idx); - -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1 - && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) - return re_string_peek_byte (pstr, idx); -#endif - - off = pstr->cur_idx + idx; -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - off = pstr->offsets[off]; -#endif - - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - -#ifdef RE_ENABLE_I18N - /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I - this function returns CAPITAL LETTER I instead of first byte of - DOTLESS SMALL LETTER I. The latter would confuse the parser, - since peek_byte_case doesn't advance cur_idx in any way. */ - if (pstr->offsets_needed && !isascii (ch)) - return re_string_peek_byte (pstr, idx); -#endif - - return ch; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_fetch_byte_case (re_string_t *pstr) -{ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_fetch_byte (pstr); - -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - { - Idx off; - int ch; - - /* For tr_TR.UTF-8 [[:islower:]] there is - [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip - in that case the whole multi-byte character and return - the original letter. On the other side, with - [[: DOTLESS SMALL LETTER I return [[:I, as doing - anything else would complicate things too much. */ - - if (!re_string_first_byte (pstr, pstr->cur_idx)) - return re_string_fetch_byte (pstr); - - off = pstr->offsets[pstr->cur_idx]; - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - - if (! isascii (ch)) - return re_string_fetch_byte (pstr); - - re_string_skip_bytes (pstr, - re_string_char_size_at (pstr, pstr->cur_idx)); - return ch; - } -#endif - - return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; -} - -static void -internal_function -re_string_destruct (re_string_t *pstr) -{ -#ifdef RE_ENABLE_I18N - re_free (pstr->wcs); - re_free (pstr->offsets); -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - re_free (pstr->mbs); -} - -/* Return the context at IDX in INPUT. */ - -static unsigned int -internal_function -re_string_context_at (const re_string_t *input, Idx idx, int eflags) -{ - int c; - if (BE (! REG_VALID_INDEX (idx), 0)) - /* In this case, we use the value stored in input->tip_context, - since we can't know the character in input->mbs[-1] here. */ - return input->tip_context; - if (BE (idx == input->len, 0)) - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc; - Idx wc_idx = idx; - while(input->wcs[wc_idx] == WEOF) - { -#ifdef DEBUG - /* It must not happen. */ - assert (REG_VALID_INDEX (wc_idx)); -#endif - --wc_idx; - if (! REG_VALID_INDEX (wc_idx)) - return input->tip_context; - } - wc = input->wcs[wc_idx]; - if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) - return CONTEXT_WORD; - return (IS_WIDE_NEWLINE (wc) && input->newline_anchor - ? CONTEXT_NEWLINE : 0); - } - else -#endif - { - c = re_string_byte_at (input, idx); - if (bitset_contain (input->word_char, c)) - return CONTEXT_WORD; - return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; - } -} - -/* Functions for set operation. */ - -static reg_errcode_t -internal_function -re_node_set_alloc (re_node_set *set, Idx size) -{ - set->alloc = size; - set->nelem = 0; - set->elems = re_malloc (Idx, size); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_1 (re_node_set *set, Idx elem) -{ - set->alloc = 1; - set->nelem = 1; - set->elems = re_malloc (Idx, 1); - if (BE (set->elems == NULL, 0)) - { - set->alloc = set->nelem = 0; - return REG_ESPACE; - } - set->elems[0] = elem; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) -{ - set->alloc = 2; - set->elems = re_malloc (Idx, 2); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - if (elem1 == elem2) - { - set->nelem = 1; - set->elems[0] = elem1; - } - else - { - set->nelem = 2; - if (elem1 < elem2) - { - set->elems[0] = elem1; - set->elems[1] = elem2; - } - else - { - set->elems[0] = elem2; - set->elems[1] = elem1; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_copy (re_node_set *dest, const re_node_set *src) -{ - dest->nelem = src->nelem; - if (src->nelem > 0) - { - dest->alloc = dest->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (BE (dest->elems == NULL, 0)) - { - dest->alloc = dest->nelem = 0; - return REG_ESPACE; - } - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - } - else - re_node_set_init_empty (dest); - return REG_NOERROR; -} - -/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. - Note: We assume dest->elems is NULL, when dest->alloc is 0. */ - -static reg_errcode_t -internal_function -re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, is, id, delta, sbase; - if (src1->nelem == 0 || src2->nelem == 0) - return REG_NOERROR; - - /* We need dest->nelem + 2 * elems_in_intersection; this is a - conservative estimate. */ - if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) - { - Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; - Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); - if (BE (new_elems == NULL, 0)) - return REG_ESPACE; - dest->elems = new_elems; - dest->alloc = new_alloc; - } - - /* Find the items in the intersection of SRC1 and SRC2, and copy - into the top of DEST those that are not already in DEST itself. */ - sbase = dest->nelem + src1->nelem + src2->nelem; - i1 = src1->nelem - 1; - i2 = src2->nelem - 1; - id = dest->nelem - 1; - for (;;) - { - if (src1->elems[i1] == src2->elems[i2]) - { - /* Try to find the item in DEST. Maybe we could binary search? */ - while (REG_VALID_INDEX (id) && dest->elems[id] > src1->elems[i1]) - --id; - - if (! REG_VALID_INDEX (id) || dest->elems[id] != src1->elems[i1]) - dest->elems[--sbase] = src1->elems[i1]; - - if (! REG_VALID_INDEX (--i1) || ! REG_VALID_INDEX (--i2)) - break; - } - - /* Lower the highest of the two items. */ - else if (src1->elems[i1] < src2->elems[i2]) - { - if (! REG_VALID_INDEX (--i2)) - break; - } - else - { - if (! REG_VALID_INDEX (--i1)) - break; - } - } - - id = dest->nelem - 1; - is = dest->nelem + src1->nelem + src2->nelem - 1; - delta = is - sbase + 1; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place; this is more or - less the same loop that is in re_node_set_merge. */ - dest->nelem += delta; - if (delta > 0 && REG_VALID_INDEX (id)) - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - break; - } - } - - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); - - return REG_NOERROR; -} - -/* Calculate the union set of the sets SRC1 and SRC2. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function -re_node_set_init_union (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, id; - if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) - { - dest->alloc = src1->nelem + src2->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (BE (dest->elems == NULL, 0)) - return REG_ESPACE; - } - else - { - if (src1 != NULL && src1->nelem > 0) - return re_node_set_init_copy (dest, src1); - else if (src2 != NULL && src2->nelem > 0) - return re_node_set_init_copy (dest, src2); - else - re_node_set_init_empty (dest); - return REG_NOERROR; - } - for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) - { - if (src1->elems[i1] > src2->elems[i2]) - { - dest->elems[id++] = src2->elems[i2++]; - continue; - } - if (src1->elems[i1] == src2->elems[i2]) - ++i2; - dest->elems[id++] = src1->elems[i1++]; - } - if (i1 < src1->nelem) - { - memcpy (dest->elems + id, src1->elems + i1, - (src1->nelem - i1) * sizeof (Idx)); - id += src1->nelem - i1; - } - else if (i2 < src2->nelem) - { - memcpy (dest->elems + id, src2->elems + i2, - (src2->nelem - i2) * sizeof (Idx)); - id += src2->nelem - i2; - } - dest->nelem = id; - return REG_NOERROR; -} - -/* Calculate the union set of the sets DEST and SRC. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function -re_node_set_merge (re_node_set *dest, const re_node_set *src) -{ - Idx is, id, sbase, delta; - if (src == NULL || src->nelem == 0) - return REG_NOERROR; - if (dest->alloc < 2 * src->nelem + dest->nelem) - { - Idx new_alloc = 2 * (src->nelem + dest->alloc); - Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); - if (BE (new_buffer == NULL, 0)) - return REG_ESPACE; - dest->elems = new_buffer; - dest->alloc = new_alloc; - } - - if (BE (dest->nelem == 0, 0)) - { - dest->nelem = src->nelem; - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - return REG_NOERROR; - } - - /* Copy into the top of DEST the items of SRC that are not - found in DEST. Maybe we could binary search in DEST? */ - for (sbase = dest->nelem + 2 * src->nelem, - is = src->nelem - 1, id = dest->nelem - 1; - REG_VALID_INDEX (is) && REG_VALID_INDEX (id); ) - { - if (dest->elems[id] == src->elems[is]) - is--, id--; - else if (dest->elems[id] < src->elems[is]) - dest->elems[--sbase] = src->elems[is--]; - else /* if (dest->elems[id] > src->elems[is]) */ - --id; - } - - if (REG_VALID_INDEX (is)) - { - /* If DEST is exhausted, the remaining items of SRC must be unique. */ - sbase -= is + 1; - memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); - } - - id = dest->nelem - 1; - is = dest->nelem + 2 * src->nelem - 1; - delta = is - sbase + 1; - if (delta == 0) - return REG_NOERROR; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place. */ - dest->nelem += delta; - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - { - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, - delta * sizeof (Idx)); - break; - } - } - } - - return REG_NOERROR; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have ELEM. - Return true if successful. */ - -static bool -internal_function -re_node_set_insert (re_node_set *set, Idx elem) -{ - Idx idx; - /* In case the set is empty. */ - if (set->alloc == 0) - return BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1); - - if (BE (set->nelem, 0) == 0) - { - /* We already guaranteed above that set->alloc != 0. */ - set->elems[0] = elem; - ++set->nelem; - return true; - } - - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = set->alloc * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (BE (new_elems == NULL, 0)) - return false; - set->elems = new_elems; - } - - /* Move the elements which follows the new element. Test the - first element separately to skip a check in the inner loop. */ - if (elem < set->elems[0]) - { - idx = 0; - for (idx = set->nelem; idx > 0; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - else - { - for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - - /* Insert the new element. */ - set->elems[idx] = elem; - ++set->nelem; - return true; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have any element greater than or equal to ELEM. - Return true if successful. */ - -static bool -internal_function -re_node_set_insert_last (re_node_set *set, Idx elem) -{ - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = (set->alloc + 1) * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (BE (new_elems == NULL, 0)) - return false; - set->elems = new_elems; - } - - /* Insert the new element. */ - set->elems[set->nelem++] = elem; - return true; -} - -/* Compare two node sets SET1 and SET2. - Return true if SET1 and SET2 are equivalent. */ - -static bool -internal_function __attribute ((pure)) -re_node_set_compare (const re_node_set *set1, const re_node_set *set2) -{ - Idx i; - if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) - return false; - for (i = set1->nelem ; REG_VALID_INDEX (--i) ; ) - if (set1->elems[i] != set2->elems[i]) - return false; - return true; -} - -/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ - -static Idx -internal_function __attribute ((pure)) -re_node_set_contains (const re_node_set *set, Idx elem) -{ - __re_size_t idx, right, mid; - if (! REG_VALID_NONZERO_INDEX (set->nelem)) - return 0; - - /* Binary search the element. */ - idx = 0; - right = set->nelem - 1; - while (idx < right) - { - mid = (idx + right) / 2; - if (set->elems[mid] < elem) - idx = mid + 1; - else - right = mid; - } - return set->elems[idx] == elem ? idx + 1 : 0; -} - -static void -internal_function -re_node_set_remove_at (re_node_set *set, Idx idx) -{ - if (idx < 0 || idx >= set->nelem) - return; - --set->nelem; - for (; idx < set->nelem; idx++) - set->elems[idx] = set->elems[idx + 1]; -} - - -/* Add the token TOKEN to dfa->nodes, and return the index of the token. - Or return REG_MISSING if an error occurred. */ - -static Idx -internal_function -re_dfa_add_node (re_dfa_t *dfa, re_token_t token) -{ - if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) - { - size_t new_nodes_alloc = dfa->nodes_alloc * 2; - Idx *new_nexts, *new_indices; - re_node_set *new_edests, *new_eclosures; - re_token_t *new_nodes; - size_t max_object_size = - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - - /* Avoid overflows. */ - if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) - return REG_MISSING; - - new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); - if (BE (new_nodes == NULL, 0)) - return REG_MISSING; - dfa->nodes = new_nodes; - new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); - new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); - new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); - new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); - if (BE (new_nexts == NULL || new_indices == NULL - || new_edests == NULL || new_eclosures == NULL, 0)) - return REG_MISSING; - dfa->nexts = new_nexts; - dfa->org_indices = new_indices; - dfa->edests = new_edests; - dfa->eclosures = new_eclosures; - dfa->nodes_alloc = new_nodes_alloc; - } - dfa->nodes[dfa->nodes_len] = token; - dfa->nodes[dfa->nodes_len].constraint = 0; -#ifdef RE_ENABLE_I18N - { - int type = token.type; - dfa->nodes[dfa->nodes_len].accept_mb = - (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; - } -#endif - dfa->nexts[dfa->nodes_len] = REG_MISSING; - re_node_set_init_empty (dfa->edests + dfa->nodes_len); - re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); - return dfa->nodes_len++; -} - -static inline re_hashval_t -internal_function -calc_state_hash (const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash = nodes->nelem + context; - Idx i; - for (i = 0 ; i < nodes->nelem ; i++) - hash += nodes->elems[i]; - return hash; -} - -/* Search for the state whose node_set is equivalent to NODES. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function -re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#ifdef lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (BE (nodes->nelem == 0, 0)) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, 0); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (hash != state->hash) - continue; - if (re_node_set_compare (&state->nodes, nodes)) - return state; - } - - /* There are no appropriate state in the dfa, create the new one. */ - new_state = create_ci_newstate (dfa, nodes, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Search for the state whose node_set is equivalent to NODES and - whose context is equivalent to CONTEXT. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function -re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#ifdef lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (nodes->nelem == 0) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, context); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (state->hash == hash - && state->context == context - && re_node_set_compare (state->entrance_nodes, nodes)) - return state; - } - /* There are no appropriate state in `dfa', create the new one. */ - new_state = create_cd_newstate (dfa, nodes, context, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Finish initialization of the new state NEWSTATE, and using its hash value - HASH put in the appropriate bucket of DFA's state table. Return value - indicates the error code if failed. */ - -static reg_errcode_t -register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, - re_hashval_t hash) -{ - struct re_state_table_entry *spot; - reg_errcode_t err; - Idx i; - - newstate->hash = hash; - err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < newstate->nodes.nelem; i++) - { - Idx elem = newstate->nodes.elems[i]; - if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) - return REG_ESPACE; - } - - spot = dfa->state_table + (hash & dfa->state_hash_mask); - if (BE (spot->alloc <= spot->num, 0)) - { - Idx new_alloc = 2 * spot->num + 2; - re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, - new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - spot->array = new_array; - spot->alloc = new_alloc; - } - spot->array[spot->num++] = newstate; - return REG_NOERROR; -} - -static void -free_state (re_dfastate_t *state) -{ - re_node_set_free (&state->non_eps_nodes); - re_node_set_free (&state->inveclosure); - if (state->entrance_nodes != &state->nodes) - { - re_node_set_free (state->entrance_nodes); - re_free (state->entrance_nodes); - } - re_node_set_free (&state->nodes); - re_free (state->word_trtable); - re_free (state->trtable); - re_free (state); -} - -/* Create the new state which is independ of contexts. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function -create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - re_hashval_t hash) -{ - Idx i; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->entrance_nodes = &newstate->nodes; - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (type == CHARACTER && !node->constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR || node->constraint) - newstate->has_constraint = 1; - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} - -/* Create the new state which is depend on the context CONTEXT. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function -create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - unsigned int context, re_hashval_t hash) -{ - Idx i, nctx_nodes = 0; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->context = context; - newstate->entrance_nodes = &newstate->nodes; - - for (i = 0 ; i < nodes->nelem ; i++) - { - unsigned int constraint = 0; - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (node->constraint) - constraint = node->constraint; - - if (type == CHARACTER && !constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR) - constraint = node->opr.ctx_type; - - if (constraint) - { - if (newstate->entrance_nodes == &newstate->nodes) - { - newstate->entrance_nodes = re_malloc (re_node_set, 1); - if (BE (newstate->entrance_nodes == NULL, 0)) - { - free_state (newstate); - return NULL; - } - re_node_set_init_copy (newstate->entrance_nodes, nodes); - nctx_nodes = 0; - newstate->has_constraint = 1; - } - - if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) - { - re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); - ++nctx_nodes; - } - } - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} diff --git a/src/bin/m4/lib/regex_internal.h b/src/bin/m4/lib/regex_internal.h deleted file mode 100644 index cc9b5b79c2..0000000000 --- a/src/bin/m4/lib/regex_internal.h +++ /dev/null @@ -1,865 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _REGEX_INTERNAL_H -#define _REGEX_INTERNAL_H 1 - -#include -#include -#include -#include -#include -#include - -#ifndef _LIBC -# include "strcase.h" -#endif - -#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC -# include -#endif -#if defined HAVE_LOCALE_H || defined _LIBC -# include -#endif -#if defined HAVE_WCHAR_H || defined _LIBC -# include -#endif /* HAVE_WCHAR_H || _LIBC */ -#if defined HAVE_WCTYPE_H || defined _LIBC -# include -#endif /* HAVE_WCTYPE_H || _LIBC */ -#include -#if defined _LIBC -# include -#else -# define __libc_lock_init(NAME) do { } while (0) -# define __libc_lock_lock(NAME) do { } while (0) -# define __libc_lock_unlock(NAME) do { } while (0) -#endif - -/* In case that the system doesn't have isblank(). */ -#if !defined _LIBC && !HAVE_DECL_ISBLANK && !defined isblank -# define isblank(ch) ((ch) == ' ' || (ch) == '\t') -#endif - -#ifdef _LIBC -# ifndef _RE_DEFINE_LOCALE_FUNCTIONS -# define _RE_DEFINE_LOCALE_FUNCTIONS 1 -# include -# include -# include -# endif -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -# include -# ifdef _LIBC -# undef gettext -# define gettext(msgid) \ - INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) -# endif -#else -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif - -/* For loser systems without the definition. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC -# define RE_ENABLE_I18N -#endif - -#if __GNUC__ >= 3 -# define BE(expr, val) __builtin_expect (expr, val) -#else -# define BE(expr, val) (expr) -# ifdef _LIBC -# define inline -# endif -#endif - -/* Number of ASCII characters. */ -#define ASCII_CHARS 0x80 - -/* Number of single byte characters. */ -#define SBC_MAX (UCHAR_MAX + 1) - -#define COLL_ELEM_LEN_MAX 8 - -/* The character which represents newline. */ -#define NEWLINE_CHAR '\n' -#define WIDE_NEWLINE_CHAR L'\n' - -/* Rename to standard API for using out of glibc. */ -#ifndef _LIBC -# define __wctype wctype -# define __iswctype iswctype -# define __btowc btowc -# ifndef __mempcpy -# define __mempcpy mempcpy -# endif -# define __wcrtomb wcrtomb -# define __regfree regfree -# define attribute_hidden -#endif /* not _LIBC */ - -#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define __attribute(arg) __attribute__ (arg) -#else -# define __attribute(arg) -#endif - -typedef __re_idx_t Idx; - -/* Special return value for failure to match. */ -#define REG_MISSING ((Idx) -1) - -/* Special return value for internal error. */ -#define REG_ERROR ((Idx) -2) - -/* Test whether N is a valid index, and is not one of the above. */ -#ifdef _REGEX_LARGE_OFFSETS -# define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR) -#else -# define REG_VALID_INDEX(n) (0 <= (n)) -#endif - -/* Test whether N is a valid nonzero index. */ -#ifdef _REGEX_LARGE_OFFSETS -# define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1)) -#else -# define REG_VALID_NONZERO_INDEX(n) (0 < (n)) -#endif - -/* A hash value, suitable for computing hash tables. */ -typedef __re_size_t re_hashval_t; - -/* An integer used to represent a set of bits. It must be unsigned, - and must be at least as wide as unsigned int. */ -typedef unsigned long int bitset_word_t; -/* All bits set in a bitset_word_t. */ -#define BITSET_WORD_MAX ULONG_MAX - -/* Number of bits in a bitset_word_t. For portability to hosts with - padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)'; - instead, deduce it directly from BITSET_WORD_MAX. Avoid - greater-than-32-bit integers and unconditional shifts by more than - 31 bits, as they're not portable. */ -#if BITSET_WORD_MAX == 0xffffffff -# define BITSET_WORD_BITS 32 -#elif BITSET_WORD_MAX >> 31 >> 5 == 1 -# define BITSET_WORD_BITS 36 -#elif BITSET_WORD_MAX >> 31 >> 16 == 1 -# define BITSET_WORD_BITS 48 -#elif BITSET_WORD_MAX >> 31 >> 28 == 1 -# define BITSET_WORD_BITS 60 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1 -# define BITSET_WORD_BITS 64 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1 -# define BITSET_WORD_BITS 72 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1 -# define BITSET_WORD_BITS 128 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1 -# define BITSET_WORD_BITS 256 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1 -# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */ -# if BITSET_WORD_BITS <= SBC_MAX -# error "Invalid SBC_MAX" -# endif -#elif BITSET_WORD_MAX == (0xffffffff + 2) * 0xffffffff -/* Work around a bug in 64-bit PGC (before version 6.1-2), where the - preprocessor mishandles large unsigned values as if they were signed. */ -# define BITSET_WORD_BITS 64 -#else -# error "Add case for new bitset_word_t size" -#endif - -/* Number of bitset_word_t values in a bitset_t. */ -#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) - -typedef bitset_word_t bitset_t[BITSET_WORDS]; -typedef bitset_word_t *re_bitset_ptr_t; -typedef const bitset_word_t *re_const_bitset_ptr_t; - -#define PREV_WORD_CONSTRAINT 0x0001 -#define PREV_NOTWORD_CONSTRAINT 0x0002 -#define NEXT_WORD_CONSTRAINT 0x0004 -#define NEXT_NOTWORD_CONSTRAINT 0x0008 -#define PREV_NEWLINE_CONSTRAINT 0x0010 -#define NEXT_NEWLINE_CONSTRAINT 0x0020 -#define PREV_BEGBUF_CONSTRAINT 0x0040 -#define NEXT_ENDBUF_CONSTRAINT 0x0080 -#define WORD_DELIM_CONSTRAINT 0x0100 -#define NOT_WORD_DELIM_CONSTRAINT 0x0200 - -typedef enum -{ - INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - LINE_FIRST = PREV_NEWLINE_CONSTRAINT, - LINE_LAST = NEXT_NEWLINE_CONSTRAINT, - BUF_FIRST = PREV_BEGBUF_CONSTRAINT, - BUF_LAST = NEXT_ENDBUF_CONSTRAINT, - WORD_DELIM = WORD_DELIM_CONSTRAINT, - NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT -} re_context_type; - -typedef struct -{ - Idx alloc; - Idx nelem; - Idx *elems; -} re_node_set; - -typedef enum -{ - NON_TYPE = 0, - - /* Node type, These are used by token, node, tree. */ - CHARACTER = 1, - END_OF_RE = 2, - SIMPLE_BRACKET = 3, - OP_BACK_REF = 4, - OP_PERIOD = 5, -#ifdef RE_ENABLE_I18N - COMPLEX_BRACKET = 6, - OP_UTF8_PERIOD = 7, -#endif /* RE_ENABLE_I18N */ - - /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used - when the debugger shows values of this enum type. */ -#define EPSILON_BIT 8 - OP_OPEN_SUBEXP = EPSILON_BIT | 0, - OP_CLOSE_SUBEXP = EPSILON_BIT | 1, - OP_ALT = EPSILON_BIT | 2, - OP_DUP_ASTERISK = EPSILON_BIT | 3, - ANCHOR = EPSILON_BIT | 4, - - /* Tree type, these are used only by tree. */ - CONCAT = 16, - SUBEXP = 17, - - /* Token type, these are used only by token. */ - OP_DUP_PLUS = 18, - OP_DUP_QUESTION, - OP_OPEN_BRACKET, - OP_CLOSE_BRACKET, - OP_CHARSET_RANGE, - OP_OPEN_DUP_NUM, - OP_CLOSE_DUP_NUM, - OP_NON_MATCH_LIST, - OP_OPEN_COLL_ELEM, - OP_CLOSE_COLL_ELEM, - OP_OPEN_EQUIV_CLASS, - OP_CLOSE_EQUIV_CLASS, - OP_OPEN_CHAR_CLASS, - OP_CLOSE_CHAR_CLASS, - OP_WORD, - OP_NOTWORD, - OP_SPACE, - OP_NOTSPACE, - BACK_SLASH - -} re_token_type_t; - -#ifdef RE_ENABLE_I18N -typedef struct -{ - /* Multibyte characters. */ - wchar_t *mbchars; - - /* Collating symbols. */ -# ifdef _LIBC - int32_t *coll_syms; -# endif - - /* Equivalence classes. */ -# ifdef _LIBC - int32_t *equiv_classes; -# endif - - /* Range expressions. */ -# ifdef _LIBC - uint32_t *range_starts; - uint32_t *range_ends; -# else /* not _LIBC */ - wchar_t *range_starts; - wchar_t *range_ends; -# endif /* not _LIBC */ - - /* Character classes. */ - wctype_t *char_classes; - - /* If this character set is the non-matching list. */ - unsigned int non_match : 1; - - /* # of multibyte characters. */ - Idx nmbchars; - - /* # of collating symbols. */ - Idx ncoll_syms; - - /* # of equivalence classes. */ - Idx nequiv_classes; - - /* # of range expressions. */ - Idx nranges; - - /* # of character classes. */ - Idx nchar_classes; -} re_charset_t; -#endif /* RE_ENABLE_I18N */ - -typedef struct -{ - union - { - unsigned char c; /* for CHARACTER */ - re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; /* for COMPLEX_BRACKET */ -#endif /* RE_ENABLE_I18N */ - Idx idx; /* for BACK_REF */ - re_context_type ctx_type; /* for ANCHOR */ - } opr; -#if __GNUC__ >= 2 - re_token_type_t type : 8; -#else - re_token_type_t type; -#endif - unsigned int constraint : 10; /* context constraint */ - unsigned int duplicated : 1; - unsigned int opt_subexp : 1; -#ifdef RE_ENABLE_I18N - unsigned int accept_mb : 1; - /* These 2 bits can be moved into the union if needed (e.g. if running out - of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ - unsigned int mb_partial : 1; -#endif - unsigned int word_char : 1; -} re_token_t; - -#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) - -struct re_string_t -{ - /* Indicate the raw buffer which is the original string passed as an - argument of regexec(), re_search(), etc.. */ - const unsigned char *raw_mbs; - /* Store the multibyte string. In case of "case insensitive mode" like - REG_ICASE, upper cases of the string are stored, otherwise MBS points - the same address that RAW_MBS points. */ - unsigned char *mbs; -#ifdef RE_ENABLE_I18N - /* Store the wide character string which is corresponding to MBS. */ - wint_t *wcs; - Idx *offsets; - mbstate_t cur_state; -#endif - /* Index in RAW_MBS. Each character mbs[i] corresponds to - raw_mbs[raw_mbs_idx + i]. */ - Idx raw_mbs_idx; - /* The length of the valid characters in the buffers. */ - Idx valid_len; - /* The corresponding number of bytes in raw_mbs array. */ - Idx valid_raw_len; - /* The length of the buffers MBS and WCS. */ - Idx bufs_len; - /* The index in MBS, which is updated by re_string_fetch_byte. */ - Idx cur_idx; - /* length of RAW_MBS array. */ - Idx raw_len; - /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ - Idx len; - /* End of the buffer may be shorter than its length in the cases such - as re_match_2, re_search_2. Then, we use STOP for end of the buffer - instead of LEN. */ - Idx raw_stop; - /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ - Idx stop; - - /* The context of mbs[0]. We store the context independently, since - the context of mbs[0] may be different from raw_mbs[0], which is - the beginning of the input string. */ - unsigned int tip_context; - /* The translation passed as a part of an argument of re_compile_pattern. */ - RE_TRANSLATE_TYPE trans; - /* Copy of re_dfa_t's word_char. */ - re_const_bitset_ptr_t word_char; - /* true if REG_ICASE. */ - unsigned char icase; - unsigned char is_utf8; - unsigned char map_notascii; - unsigned char mbs_allocated; - unsigned char offsets_needed; - unsigned char newline_anchor; - unsigned char word_ops_used; - int mb_cur_max; -}; -typedef struct re_string_t re_string_t; - - -struct re_dfa_t; -typedef struct re_dfa_t re_dfa_t; - -#ifndef _LIBC -# ifdef __i386__ -# define internal_function __attribute ((regparm (3), stdcall)) -# else -# define internal_function -# endif -#endif - -static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, - Idx new_buf_len) - internal_function; -#ifdef RE_ENABLE_I18N -static void build_wcs_buffer (re_string_t *pstr) internal_function; -static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) - internal_function; -#endif /* RE_ENABLE_I18N */ -static void build_upper_buffer (re_string_t *pstr) internal_function; -static void re_string_translate_buffer (re_string_t *pstr) internal_function; -static unsigned int re_string_context_at (const re_string_t *input, Idx idx, - int eflags) - internal_function __attribute ((pure)); -#define re_string_peek_byte(pstr, offset) \ - ((pstr)->mbs[(pstr)->cur_idx + offset]) -#define re_string_fetch_byte(pstr) \ - ((pstr)->mbs[(pstr)->cur_idx++]) -#define re_string_first_byte(pstr, idx) \ - ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) -#define re_string_is_single_byte_char(pstr, idx) \ - ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ - || (pstr)->wcs[(idx) + 1] != WEOF)) -#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) -#define re_string_cur_idx(pstr) ((pstr)->cur_idx) -#define re_string_get_buffer(pstr) ((pstr)->mbs) -#define re_string_length(pstr) ((pstr)->len) -#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) -#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) -#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) - -#include - -#ifndef _LIBC -# if HAVE_ALLOCA -/* The OS usually guarantees only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - allocate anything larger than 4096 bytes. Also care for the possibility - of a few compiler-allocated temporary stack slots. */ -# define __libc_use_alloca(n) ((n) < 4032) -# else -/* alloca is implemented with malloc, so just use malloc. */ -# define __libc_use_alloca(n) 0 -# endif -#endif - -#ifndef MAX -# define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) -#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) -#define re_free(p) free (p) - -struct bin_tree_t -{ - struct bin_tree_t *parent; - struct bin_tree_t *left; - struct bin_tree_t *right; - struct bin_tree_t *first; - struct bin_tree_t *next; - - re_token_t token; - - /* `node_idx' is the index in dfa->nodes, if `type' == 0. - Otherwise `type' indicate the type of this node. */ - Idx node_idx; -}; -typedef struct bin_tree_t bin_tree_t; - -#define BIN_TREE_STORAGE_SIZE \ - ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) - -struct bin_tree_storage_t -{ - struct bin_tree_storage_t *next; - bin_tree_t data[BIN_TREE_STORAGE_SIZE]; -}; -typedef struct bin_tree_storage_t bin_tree_storage_t; - -#define CONTEXT_WORD 1 -#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) -#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) -#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) - -#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) -#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) -#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) -#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) -#define IS_ORDINARY_CONTEXT(c) ((c) == 0) - -#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') -#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) -#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') -#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) - -#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ - ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ - || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) - -#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ - ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ - || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) - -struct re_dfastate_t -{ - re_hashval_t hash; - re_node_set nodes; - re_node_set non_eps_nodes; - re_node_set inveclosure; - re_node_set *entrance_nodes; - struct re_dfastate_t **trtable, **word_trtable; - unsigned int context : 4; - unsigned int halt : 1; - /* If this state can accept `multi byte'. - Note that we refer to multibyte characters, and multi character - collating elements as `multi byte'. */ - unsigned int accept_mb : 1; - /* If this state has backreference node(s). */ - unsigned int has_backref : 1; - unsigned int has_constraint : 1; -}; -typedef struct re_dfastate_t re_dfastate_t; - -struct re_state_table_entry -{ - Idx num; - Idx alloc; - re_dfastate_t **array; -}; - -/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ - -typedef struct -{ - Idx next_idx; - Idx alloc; - re_dfastate_t **array; -} state_array_t; - -/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ - -typedef struct -{ - Idx node; - Idx str_idx; /* The position NODE match at. */ - state_array_t path; -} re_sub_match_last_t; - -/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. - And information about the node, whose type is OP_CLOSE_SUBEXP, - corresponding to NODE is stored in LASTS. */ - -typedef struct -{ - Idx str_idx; - Idx node; - state_array_t *path; - Idx alasts; /* Allocation size of LASTS. */ - Idx nlasts; /* The number of LASTS. */ - re_sub_match_last_t **lasts; -} re_sub_match_top_t; - -struct re_backref_cache_entry -{ - Idx node; - Idx str_idx; - Idx subexp_from; - Idx subexp_to; - char more; - char unused; - unsigned short int eps_reachable_subexps_map; -}; - -typedef struct -{ - /* The string object corresponding to the input string. */ - re_string_t input; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - const re_dfa_t *const dfa; -#else - const re_dfa_t *dfa; -#endif - /* EFLAGS of the argument of regexec. */ - int eflags; - /* Where the matching ends. */ - Idx match_last; - Idx last_node; - /* The state log used by the matcher. */ - re_dfastate_t **state_log; - Idx state_log_top; - /* Back reference cache. */ - Idx nbkref_ents; - Idx abkref_ents; - struct re_backref_cache_entry *bkref_ents; - int max_mb_elem_len; - Idx nsub_tops; - Idx asub_tops; - re_sub_match_top_t **sub_tops; -} re_match_context_t; - -typedef struct -{ - re_dfastate_t **sifted_states; - re_dfastate_t **limited_states; - Idx last_node; - Idx last_str_idx; - re_node_set limits; -} re_sift_context_t; - -struct re_fail_stack_ent_t -{ - Idx idx; - Idx node; - regmatch_t *regs; - re_node_set eps_via_nodes; -}; - -struct re_fail_stack_t -{ - Idx num; - Idx alloc; - struct re_fail_stack_ent_t *stack; -}; - -struct re_dfa_t -{ - re_token_t *nodes; - size_t nodes_alloc; - size_t nodes_len; - Idx *nexts; - Idx *org_indices; - re_node_set *edests; - re_node_set *eclosures; - re_node_set *inveclosures; - struct re_state_table_entry *state_table; - re_dfastate_t *init_state; - re_dfastate_t *init_state_word; - re_dfastate_t *init_state_nl; - re_dfastate_t *init_state_begbuf; - bin_tree_t *str_tree; - bin_tree_storage_t *str_tree_storage; - re_bitset_ptr_t sb_char; - int str_tree_storage_idx; - - /* number of subexpressions `re_nsub' is in regex_t. */ - re_hashval_t state_hash_mask; - Idx init_node; - Idx nbackref; /* The number of backreference in this dfa. */ - - /* Bitmap expressing which backreference is used. */ - bitset_word_t used_bkref_map; - bitset_word_t completed_bkref_map; - - unsigned int has_plural_match : 1; - /* If this dfa has "multibyte node", which is a backreference or - a node which can accept multibyte character or multi character - collating element. */ - unsigned int has_mb_node : 1; - unsigned int is_utf8 : 1; - unsigned int map_notascii : 1; - unsigned int word_ops_used : 1; - int mb_cur_max; - bitset_t word_char; - reg_syntax_t syntax; - Idx *subexp_map; -#ifdef DEBUG - char* re_str; -#endif -#ifdef _LIBC - __libc_lock_define (, lock) -#endif -}; - -#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) -#define re_node_set_remove(set,id) \ - (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) -#define re_node_set_empty(p) ((p)->nelem = 0) -#define re_node_set_free(set) re_free ((set)->elems) - - -typedef enum -{ - SB_CHAR, - MB_CHAR, - EQUIV_CLASS, - COLL_SYM, - CHAR_CLASS -} bracket_elem_type; - -typedef struct -{ - bracket_elem_type type; - union - { - unsigned char ch; - unsigned char *name; - wchar_t wch; - } opr; -} bracket_elem_t; - - -/* Inline functions for bitset_t operation. */ - -static inline void -bitset_set (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; -} - -static inline void -bitset_clear (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); -} - -static inline bool -bitset_contain (const bitset_t set, Idx i) -{ - return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; -} - -static inline void -bitset_empty (bitset_t set) -{ - memset (set, '\0', sizeof (bitset_t)); -} - -static inline void -bitset_set_all (bitset_t set) -{ - memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; -} - -static inline void -bitset_copy (bitset_t dest, const bitset_t src) -{ - memcpy (dest, src, sizeof (bitset_t)); -} - -static inline void -bitset_not (bitset_t set) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) - set[bitset_i] = ~set[bitset_i]; - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) - & ~set[BITSET_WORDS - 1]); -} - -static inline void -bitset_merge (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] |= src[bitset_i]; -} - -static inline void -bitset_mask (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] &= src[bitset_i]; -} - -#ifdef RE_ENABLE_I18N -/* Inline functions for re_string. */ -static inline int -internal_function __attribute ((pure)) -re_string_char_size_at (const re_string_t *pstr, Idx idx) -{ - int byte_idx; - if (pstr->mb_cur_max == 1) - return 1; - for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) - if (pstr->wcs[idx + byte_idx] != WEOF) - break; - return byte_idx; -} - -static inline wint_t -internal_function __attribute ((pure)) -re_string_wchar_at (const re_string_t *pstr, Idx idx) -{ - if (pstr->mb_cur_max == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; -} - -static int -internal_function __attribute ((pure)) -re_string_elem_size_at (const re_string_t *pstr, Idx idx) -{ -# ifdef _LIBC - const unsigned char *p, *extra; - const int32_t *table, *indirect; - int32_t tmp; -# include - uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - - if (nrules != 0) - { - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - p = pstr->mbs + idx; - tmp = findidx (&p); - return p - pstr->mbs - idx; - } - else -# endif /* _LIBC */ - return 1; -} -#endif /* RE_ENABLE_I18N */ - -#endif /* _REGEX_INTERNAL_H */ diff --git a/src/bin/m4/lib/regexec.c b/src/bin/m4/lib/regexec.c deleted file mode 100644 index 84c3aed634..0000000000 --- a/src/bin/m4/lib/regexec.c +++ /dev/null @@ -1,4398 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, - Idx n) internal_function; -static void match_ctx_clean (re_match_context_t *mctx) internal_function; -static void match_ctx_free (re_match_context_t *cache) internal_function; -static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node, - Idx str_idx, Idx from, Idx to) - internal_function; -static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) - internal_function; -static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node, - Idx str_idx) internal_function; -static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, - Idx node, Idx str_idx) - internal_function; -static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, - Idx last_str_idx) - internal_function; -static reg_errcode_t re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) internal_function; -static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, - struct re_registers *regs, - Idx stop, bool ret_len) internal_function; -static regoff_t re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, Idx start, - regoff_t range, Idx stop, - struct re_registers *regs, - bool ret_len) internal_function; -static unsigned int re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - Idx nregs, int regs_allocated) - internal_function; -static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) - internal_function; -static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) internal_function; -static Idx check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) - internal_function; -static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, - Idx cur_idx, Idx nmatch) internal_function; -static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, - Idx str_idx, Idx dest_node, Idx nregs, - regmatch_t *regs, - re_node_set *eps_via_nodes) - internal_function; -static reg_errcode_t set_regs (const regex_t *preg, - const re_match_context_t *mctx, - size_t nmatch, regmatch_t *pmatch, - bool fl_backtrack) internal_function; -static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) - internal_function; - -#ifdef RE_ENABLE_I18N -static int sift_states_iter_mb (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, - re_sift_context_t *sctx) - internal_function; -static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *cur_dest) - internal_function; -static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, - re_node_set *dest_nodes) - internal_function; -static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates) - internal_function; -static bool check_dst_limits (const re_match_context_t *mctx, - const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, - Idx src_idx) internal_function; -static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, - int boundaries, Idx subexp_idx, - Idx from_node, Idx bkref_idx) - internal_function; -static int check_dst_limits_calc_pos (const re_match_context_t *mctx, - Idx limit, Idx subexp_idx, - Idx node, Idx str_idx, - Idx bkref_idx) internal_function; -static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates, - re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, - Idx str_idx) internal_function; -static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) - internal_function; -static reg_errcode_t merge_state_array (const re_dfa_t *dfa, - re_dfastate_t **dst, - re_dfastate_t **src, Idx num) - internal_function; -static re_dfastate_t *find_recover_state (reg_errcode_t *err, - re_match_context_t *mctx) internal_function; -static re_dfastate_t *transit_state (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *state) internal_function; -static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *next_state) - internal_function; -static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, - re_node_set *cur_nodes, - Idx str_idx) internal_function; -#if 0 -static re_dfastate_t *transit_state_sb (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif -#ifdef RE_ENABLE_I18N -static reg_errcode_t transit_state_mb (re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, - const re_node_set *nodes) - internal_function; -static reg_errcode_t get_subexp (re_match_context_t *mctx, - Idx bkref_node, Idx bkref_str_idx) - internal_function; -static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, - const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, - Idx bkref_node, Idx bkref_str) - internal_function; -static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) internal_function; -static reg_errcode_t check_arrival (re_match_context_t *mctx, - state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, - int type) internal_function; -static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, - Idx str_idx, - re_node_set *cur_nodes, - re_node_set *next_nodes) - internal_function; -static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, - re_node_set *cur_nodes, - Idx ex_subexp, int type) - internal_function; -static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, - re_node_set *dst_nodes, - Idx target, Idx ex_subexp, - int type) internal_function; -static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, - re_node_set *cur_nodes, Idx cur_str, - Idx subexp_num, int type) - internal_function; -static bool build_trtable (const re_dfa_t *dfa, - re_dfastate_t *state) internal_function; -#ifdef RE_ENABLE_I18N -static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx idx) - internal_function; -# ifdef _LIBC -static unsigned int find_collation_sequence_value (const unsigned char *mbs, - size_t name_len) - internal_function; -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ -static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, - const re_dfastate_t *state, - re_node_set *states_node, - bitset_t *states_ch) internal_function; -static bool check_node_accept (const re_match_context_t *mctx, - const re_token_t *node, Idx idx) - internal_function; -static reg_errcode_t extend_buffers (re_match_context_t *mctx) - internal_function; - -/* Entry point for POSIX code. */ - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies `execution flags' which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - We return 0 if we find a match and REG_NOMATCH if not. */ - -int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *__restrict preg; - const char *__restrict string; - size_t nmatch; - regmatch_t pmatch[]; - int eflags; -{ - reg_errcode_t err; - Idx start, length; -#ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; -#endif - - if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) - return REG_BADPAT; - - if (eflags & REG_STARTEND) - { - start = pmatch[0].rm_so; - length = pmatch[0].rm_eo; - } - else - { - start = 0; - length = strlen (string); - } - - __libc_lock_lock (dfa->lock); - if (preg->no_sub) - err = re_search_internal (preg, string, length, start, length, - length, 0, NULL, eflags); - else - err = re_search_internal (preg, string, length, start, length, - length, nmatch, pmatch, eflags); - __libc_lock_unlock (dfa->lock); - return err != REG_NOERROR; -} - -#ifdef _LIBC -# include -versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); - -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -__typeof__ (__regexec) __compat_regexec; - -int -attribute_compat_text_section -__compat_regexec (const regex_t *__restrict preg, - const char *__restrict string, size_t nmatch, - regmatch_t pmatch[], int eflags) -{ - return regexec (preg, string, nmatch, pmatch, - eflags & (REG_NOTBOL | REG_NOTEOL)); -} -compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); -# endif -#endif - -/* Entry points for GNU code. */ - -/* re_match, re_search, re_match_2, re_search_2 - - The former two functions operate on STRING with length LENGTH, - while the later two operate on concatenation of STRING1 and STRING2 - with lengths LENGTH1 and LENGTH2, respectively. - - re_match() matches the compiled pattern in BUFP against the string, - starting at index START. - - re_search() first tries matching at index START, then it tries to match - starting from index START + 1, and so on. The last start position tried - is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same - way as re_match().) - - The parameter STOP of re_{match,search}_2 specifies that no match exceeding - the first STOP characters of the concatenation of the strings should be - concerned. - - If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stored in REGS. (For the "_2" variants, the offsets are - computed relative to the concatenation, not relative to the individual - strings.) - - On success, re_match* functions return the length of the match, re_search* - return the position of the start of the match. Return value -1 means no - match was found and -2 indicates an internal error. */ - -regoff_t -re_match (bufp, string, length, start, regs) - struct re_pattern_buffer *bufp; - const char *string; - Idx length, start; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, 0, length, regs, true); -} -#ifdef _LIBC -weak_alias (__re_match, re_match) -#endif - -regoff_t -re_search (bufp, string, length, start, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - Idx length, start; - regoff_t range; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, range, length, regs, - false); -} -#ifdef _LIBC -weak_alias (__re_search, re_search) -#endif - -regoff_t -re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - Idx length1, length2, start, stop; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, 0, regs, stop, true); -} -#ifdef _LIBC -weak_alias (__re_match_2, re_match_2) -#endif - -regoff_t -re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - Idx length1, length2, start, stop; - regoff_t range; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, range, regs, stop, false); -} -#ifdef _LIBC -weak_alias (__re_search_2, re_search_2) -#endif - -static regoff_t -internal_function -re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, struct re_registers *regs, - Idx stop, bool ret_len) -{ - const char *str; - regoff_t rval; - Idx len = length1 + length2; - char *s = NULL; - - if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0)) - return -2; - - /* Concatenate the strings. */ - if (length2 > 0) - if (length1 > 0) - { - s = re_malloc (char, len); - - if (BE (s == NULL, 0)) - return -2; -#ifdef _LIBC - memcpy (__mempcpy (s, string1, length1), string2, length2); -#else - memcpy (s, string1, length1); - memcpy (s + length1, string2, length2); -#endif - str = s; - } - else - str = string2; - else - str = string1; - - rval = re_search_stub (bufp, str, len, start, range, stop, regs, - ret_len); - re_free (s); - return rval; -} - -/* The parameters have the same meaning as those of re_search. - Additional parameters: - If RET_LEN is true the length of the match is returned (re_match style); - otherwise the position of the match is returned. */ - -static regoff_t -internal_function -re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, - Idx start, regoff_t range, Idx stop, struct re_registers *regs, - bool ret_len) -{ - reg_errcode_t result; - regmatch_t *pmatch; - Idx nregs; - regoff_t rval; - int eflags = 0; -#ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; -#endif - Idx last_start = start + range; - - /* Check for out-of-range. */ - if (BE (start < 0 || start > length, 0)) - return -1; - if (BE (length < last_start || (0 <= range && last_start < start), 0)) - last_start = length; - else if (BE (last_start < 0 || (range < 0 && start <= last_start), 0)) - last_start = 0; - - __libc_lock_lock (dfa->lock); - - eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; - eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; - - /* Compile fastmap if we haven't yet. */ - if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate) - re_compile_fastmap (bufp); - - if (BE (bufp->no_sub, 0)) - regs = NULL; - - /* We need at least 1 register. */ - if (regs == NULL) - nregs = 1; - else if (BE (bufp->regs_allocated == REGS_FIXED - && regs->num_regs <= bufp->re_nsub, 0)) - { - nregs = regs->num_regs; - if (BE (nregs < 1, 0)) - { - /* Nothing can be copied to regs. */ - regs = NULL; - nregs = 1; - } - } - else - nregs = bufp->re_nsub + 1; - pmatch = re_malloc (regmatch_t, nregs); - if (BE (pmatch == NULL, 0)) - { - rval = -2; - goto out; - } - - result = re_search_internal (bufp, string, length, start, last_start, stop, - nregs, pmatch, eflags); - - rval = 0; - - /* I hope we needn't fill ther regs with -1's when no match was found. */ - if (result != REG_NOERROR) - rval = -1; - else if (regs != NULL) - { - /* If caller wants register contents data back, copy them. */ - bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, - bufp->regs_allocated); - if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) - rval = -2; - } - - if (BE (rval == 0, 1)) - { - if (ret_len) - { - assert (pmatch[0].rm_so == start); - rval = pmatch[0].rm_eo - start; - } - else - rval = pmatch[0].rm_so; - } - re_free (pmatch); - out: - __libc_lock_unlock (dfa->lock); - return rval; -} - -static unsigned int -internal_function -re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, - int regs_allocated) -{ - int rval = REGS_REALLOCATE; - Idx i; - Idx need_regs = nregs + 1; - /* We need one extra element beyond `num_regs' for the `-1' marker GNU code - uses. */ - - /* Have the register data arrays been allocated? */ - if (regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. */ - regs->start = re_malloc (regoff_t, need_regs); - if (BE (regs->start == NULL, 0)) - return REGS_UNALLOCATED; - regs->end = re_malloc (regoff_t, need_regs); - if (BE (regs->end == NULL, 0)) - { - re_free (regs->start); - return REGS_UNALLOCATED; - } - regs->num_regs = need_regs; - } - else if (regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (BE (need_regs > regs->num_regs, 0)) - { - regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); - regoff_t *new_end; - if (BE (new_start == NULL, 0)) - return REGS_UNALLOCATED; - new_end = re_realloc (regs->end, regoff_t, need_regs); - if (BE (new_end == NULL, 0)) - { - re_free (new_start); - return REGS_UNALLOCATED; - } - regs->start = new_start; - regs->end = new_end; - regs->num_regs = need_regs; - } - } - else - { - assert (regs_allocated == REGS_FIXED); - /* This function may not be called with REGS_FIXED and nregs too big. */ - assert (regs->num_regs >= nregs); - rval = REGS_FIXED; - } - - /* Copy the regs. */ - for (i = 0; i < nregs; ++i) - { - regs->start[i] = pmatch[i].rm_so; - regs->end[i] = pmatch[i].rm_eo; - } - for ( ; i < regs->num_regs; ++i) - regs->start[i] = regs->end[i] = -1; - - return rval; -} - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - __re_size_t num_regs; - regoff_t *starts, *ends; -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = NULL; - } -} -#ifdef _LIBC -weak_alias (__re_set_registers, re_set_registers) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC -int -# ifdef _LIBC -weak_function -# endif -re_exec (s) - const char *s; -{ - return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); -} -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. */ - -/* Searches for a compiled pattern PREG in the string STRING, whose - length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same - meaning as with regexec. LAST_START is START + RANGE, where - START and RANGE have the same meaning as with re_search. - Return REG_NOERROR if we find a match, and REG_NOMATCH if not, - otherwise return the error code. - Note: We assume front end functions already check ranges. - (0 <= LAST_START && LAST_START <= LENGTH) */ - -static reg_errcode_t -internal_function -re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) -{ - reg_errcode_t err; - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - Idx left_lim, right_lim; - int incr; - bool fl_longest_match; - int match_kind; - Idx match_first; - Idx match_last = REG_MISSING; - Idx extra_nmatch; - bool sb; - int ch; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - re_match_context_t mctx = { .dfa = dfa }; -#else - re_match_context_t mctx; -#endif - char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate - && start != last_start && !preg->can_be_null) - ? preg->fastmap : NULL); - RE_TRANSLATE_TYPE t = preg->translate; - -#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) - memset (&mctx, '\0', sizeof (re_match_context_t)); - mctx.dfa = dfa; -#endif - - extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; - nmatch -= extra_nmatch; - - /* Check if the DFA haven't been compiled. */ - if (BE (preg->used == 0 || dfa->init_state == NULL - || dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return REG_NOMATCH; - -#ifdef DEBUG - /* We assume front-end functions already check them. */ - assert (0 <= last_start && last_start <= length); -#endif - - /* If initial states with non-begbuf contexts have no elements, - the regex must be anchored. If preg->newline_anchor is set, - we'll never use init_state_nl, so do not check it. */ - if (dfa->init_state->nodes.nelem == 0 - && dfa->init_state_word->nodes.nelem == 0 - && (dfa->init_state_nl->nodes.nelem == 0 - || !preg->newline_anchor)) - { - if (start != 0 && last_start != 0) - return REG_NOMATCH; - start = last_start = 0; - } - - /* We must check the longest matching, if nmatch > 0. */ - fl_longest_match = (nmatch != 0 || dfa->nbackref); - - err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, - preg->translate, preg->syntax & RE_ICASE, dfa); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - mctx.input.stop = stop; - mctx.input.raw_stop = stop; - mctx.input.newline_anchor = preg->newline_anchor; - - err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* We will log all the DFA states through which the dfa pass, - if nmatch > 1, or this dfa has "multibyte node", which is a - back-reference or a node which can accept multibyte character or - multi character collating element. */ - if (nmatch > 1 || dfa->has_mb_node) - { - /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0)) - { - err = REG_ESPACE; - goto free_return; - } - - mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); - if (BE (mctx.state_log == NULL, 0)) - { - err = REG_ESPACE; - goto free_return; - } - } - else - mctx.state_log = NULL; - - match_first = start; - mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF; - - /* Check incrementally whether of not the input string match. */ - incr = (last_start < start) ? -1 : 1; - left_lim = (last_start < start) ? last_start : start; - right_lim = (last_start < start) ? start : last_start; - sb = dfa->mb_cur_max == 1; - match_kind = - (fastmap - ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) - | (start <= last_start ? 2 : 0) - | (t != NULL ? 1 : 0)) - : 8); - - for (;; match_first += incr) - { - err = REG_NOMATCH; - if (match_first < left_lim || right_lim < match_first) - goto free_return; - - /* Advance as rapidly as possible through the string, until we - find a plausible place to start matching. This may be done - with varying efficiency, so there are various possibilities: - only the most common of them are specialized, in order to - save on code size. We use a switch statement for speed. */ - switch (match_kind) - { - case 8: - /* No fastmap. */ - break; - - case 7: - /* Fastmap with single-byte translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[t[(unsigned char) string[match_first]]]) - ++match_first; - goto forward_match_found_start_or_reached_end; - - case 6: - /* Fastmap without translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[(unsigned char) string[match_first]]) - ++match_first; - - forward_match_found_start_or_reached_end: - if (BE (match_first == right_lim, 0)) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (!fastmap[t ? t[ch] : ch]) - goto free_return; - } - break; - - case 4: - case 5: - /* Fastmap without multi-byte translation, match backwards. */ - while (match_first >= left_lim) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (fastmap[t ? t[ch] : ch]) - break; - --match_first; - } - if (match_first < left_lim) - goto free_return; - break; - - default: - /* In this case, we can't determine easily the current byte, - since it might be a component byte of a multibyte - character. Then we use the constructed buffer instead. */ - for (;;) - { - /* If MATCH_FIRST is out of the valid range, reconstruct the - buffers. */ - __re_size_t offset = match_first - mctx.input.raw_mbs_idx; - if (BE (offset >= (__re_size_t) mctx.input.valid_raw_len, 0)) - { - err = re_string_reconstruct (&mctx.input, match_first, - eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - offset = match_first - mctx.input.raw_mbs_idx; - } - /* If MATCH_FIRST is out of the buffer, leave it as '\0'. - Note that MATCH_FIRST must not be smaller than 0. */ - ch = (match_first >= length - ? 0 : re_string_byte_at (&mctx.input, offset)); - if (fastmap[ch]) - break; - match_first += incr; - if (match_first < left_lim || match_first > right_lim) - { - err = REG_NOMATCH; - goto free_return; - } - } - break; - } - - /* Reconstruct the buffers so that the matcher can assume that - the matching starts from the beginning of the buffer. */ - err = re_string_reconstruct (&mctx.input, match_first, eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - -#ifdef RE_ENABLE_I18N - /* Don't consider this char as a possible match start if it part, - yet isn't the head, of a multibyte character. */ - if (!sb && !re_string_first_byte (&mctx.input, 0)) - continue; -#endif - - /* It seems to be appropriate one, then use the matcher. */ - /* We assume that the matching starts from 0. */ - mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; - match_last = check_matching (&mctx, fl_longest_match, - start <= last_start ? &match_first : NULL); - if (match_last != REG_MISSING) - { - if (BE (match_last == REG_ERROR, 0)) - { - err = REG_ESPACE; - goto free_return; - } - else - { - mctx.match_last = match_last; - if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) - { - re_dfastate_t *pstate = mctx.state_log[match_last]; - mctx.last_node = check_halt_state_context (&mctx, pstate, - match_last); - } - if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) - || dfa->nbackref) - { - err = prune_impossible_nodes (&mctx); - if (err == REG_NOERROR) - break; - if (BE (err != REG_NOMATCH, 0)) - goto free_return; - match_last = REG_MISSING; - } - else - break; /* We found a match. */ - } - } - - match_ctx_clean (&mctx); - } - -#ifdef DEBUG - assert (match_last != REG_MISSING); - assert (err == REG_NOERROR); -#endif - - /* Set pmatch[] if we need. */ - if (nmatch > 0) - { - Idx reg_idx; - - /* Initialize registers. */ - for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) - pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; - - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - /* FIXME: This function should fail if mctx.match_last exceeds - the maximum possible regoff_t value. We need a new error - code REG_OVERFLOW. */ - - if (!preg->no_sub && nmatch > 1) - { - err = set_regs (preg, &mctx, nmatch, pmatch, - dfa->has_plural_match && dfa->nbackref > 0); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* At last, add the offset to the each registers, since we slided - the buffers so that we could assume that the matching starts - from 0. */ - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so != -1) - { -#ifdef RE_ENABLE_I18N - if (BE (mctx.input.offsets_needed != 0, 0)) - { - pmatch[reg_idx].rm_so = - (pmatch[reg_idx].rm_so == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_so]); - pmatch[reg_idx].rm_eo = - (pmatch[reg_idx].rm_eo == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_eo]); - } -#else - assert (mctx.input.offsets_needed == 0); -#endif - pmatch[reg_idx].rm_so += match_first; - pmatch[reg_idx].rm_eo += match_first; - } - for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) - { - pmatch[nmatch + reg_idx].rm_so = -1; - pmatch[nmatch + reg_idx].rm_eo = -1; - } - - if (dfa->subexp_map) - for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) - if (dfa->subexp_map[reg_idx] != reg_idx) - { - pmatch[reg_idx + 1].rm_so - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; - pmatch[reg_idx + 1].rm_eo - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; - } - } - - free_return: - re_free (mctx.state_log); - if (dfa->nbackref) - match_ctx_free (&mctx); - re_string_destruct (&mctx.input); - return err; -} - -static reg_errcode_t -internal_function -prune_impossible_nodes (re_match_context_t *mctx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx halt_node, match_last; - reg_errcode_t ret; - re_dfastate_t **sifted_states; - re_dfastate_t **lim_states = NULL; - re_sift_context_t sctx; -#ifdef DEBUG - assert (mctx->state_log != NULL); -#endif - match_last = mctx->match_last; - halt_node = mctx->last_node; - - /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0)) - return REG_ESPACE; - - sifted_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (sifted_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - if (dfa->nbackref) - { - lim_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (lim_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - while (1) - { - memset (lim_states, '\0', - sizeof (re_dfastate_t *) * (match_last + 1)); - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - if (sifted_states[0] != NULL || lim_states[0] != NULL) - break; - do - { - --match_last; - if (! REG_VALID_INDEX (match_last)) - { - ret = REG_NOMATCH; - goto free_return; - } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); - } - ret = merge_state_array (dfa, sifted_states, lim_states, - match_last + 1); - re_free (lim_states); - lim_states = NULL; - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - else - { - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - re_free (mctx->state_log); - mctx->state_log = sifted_states; - sifted_states = NULL; - mctx->last_node = halt_node; - mctx->match_last = match_last; - ret = REG_NOERROR; - free_return: - re_free (sifted_states); - re_free (lim_states); - return ret; -} - -/* Acquire an initial state and return it. - We must select appropriate initial state depending on the context, - since initial states may have constraints like "\<", "^", etc.. */ - -static inline re_dfastate_t * -__attribute ((always_inline)) internal_function -acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, - Idx idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - if (dfa->init_state->has_constraint) - { - unsigned int context; - context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return dfa->init_state_word; - else if (IS_ORDINARY_CONTEXT (context)) - return dfa->init_state; - else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_begbuf; - else if (IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_nl; - else if (IS_BEGBUF_CONTEXT (context)) - { - /* It is relatively rare case, then calculate on demand. */ - return re_acquire_state_context (err, dfa, - dfa->init_state->entrance_nodes, - context); - } - else - /* Must not happen? */ - return dfa->init_state; - } - else - return dfa->init_state; -} - -/* Check whether the regular expression match input string INPUT or not, - and return the index where the matching end. Return REG_MISSING if - there is no match, and return REG_ERROR in case of an error. - FL_LONGEST_MATCH means we want the POSIX longest matching. - If P_MATCH_FIRST is not NULL, and the match fails, it is set to the - next place where we may want to try matching. - Note that the matcher assume that the maching starts from the current - index of the buffer. */ - -static Idx -internal_function -check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx match = 0; - Idx match_last = REG_MISSING; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - re_dfastate_t *cur_state; - bool at_init_state = p_match_first != NULL; - Idx next_start_idx = cur_str_idx; - - err = REG_NOERROR; - cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); - /* An initial state must not be NULL (invalid). */ - if (BE (cur_state == NULL, 0)) - { - assert (err == REG_ESPACE); - return REG_ERROR; - } - - if (mctx->state_log != NULL) - { - mctx->state_log[cur_str_idx] = cur_state; - - /* Check OP_OPEN_SUBEXP in the initial state in case that we use them - later. E.g. Processing back references. */ - if (BE (dfa->nbackref, 0)) - { - at_init_state = false; - err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (cur_state->has_backref) - { - err = transit_state_bkref (mctx, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - - /* If the RE accepts NULL string. */ - if (BE (cur_state->halt, 0)) - { - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, cur_str_idx)) - { - if (!fl_longest_match) - return cur_str_idx; - else - { - match_last = cur_str_idx; - match = 1; - } - } - } - - while (!re_string_eoi (&mctx->input)) - { - re_dfastate_t *old_state = cur_state; - Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; - - if (BE (next_char_idx >= mctx->input.bufs_len, 0) - || (BE (next_char_idx >= mctx->input.valid_len, 0) - && mctx->input.valid_len < mctx->input.len)) - { - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - { - assert (err == REG_ESPACE); - return REG_ERROR; - } - } - - cur_state = transit_state (&err, mctx, cur_state); - if (mctx->state_log != NULL) - cur_state = merge_state_with_log (&err, mctx, cur_state); - - if (cur_state == NULL) - { - /* Reached the invalid state or an error. Try to recover a valid - state using the state log, if available and if we have not - already found a valid (even if not the longest) match. */ - if (BE (err != REG_NOERROR, 0)) - return REG_ERROR; - - if (mctx->state_log == NULL - || (match && !fl_longest_match) - || (cur_state = find_recover_state (&err, mctx)) == NULL) - break; - } - - if (BE (at_init_state, 0)) - { - if (old_state == cur_state) - next_start_idx = next_char_idx; - else - at_init_state = false; - } - - if (cur_state->halt) - { - /* Reached a halt state. - Check the halt state can satisfy the current context. */ - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, - re_string_cur_idx (&mctx->input))) - { - /* We found an appropriate halt state. */ - match_last = re_string_cur_idx (&mctx->input); - match = 1; - - /* We found a match, do not modify match_first below. */ - p_match_first = NULL; - if (!fl_longest_match) - break; - } - } - } - - if (p_match_first) - *p_match_first += next_start_idx; - - return match_last; -} - -/* Check NODE match the current context. */ - -static bool -internal_function -check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context) -{ - re_token_type_t type = dfa->nodes[node].type; - unsigned int constraint = dfa->nodes[node].constraint; - if (type != END_OF_RE) - return false; - if (!constraint) - return true; - if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) - return false; - return true; -} - -/* Check the halt state STATE match the current context. - Return 0 if not match, if the node, STATE has, is a halt node and - match the context, return the node. */ - -static Idx -internal_function -check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) -{ - Idx i; - unsigned int context; -#ifdef DEBUG - assert (state->halt); -#endif - context = re_string_context_at (&mctx->input, idx, mctx->eflags); - for (i = 0; i < state->nodes.nelem; ++i) - if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) - return state->nodes.elems[i]; - return 0; -} - -/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA - corresponding to the DFA). - Return the destination node, and update EPS_VIA_NODES; - return REG_MISSING in case of errors. */ - -static Idx -internal_function -proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, - Idx *pidx, Idx node, re_node_set *eps_via_nodes, - struct re_fail_stack_t *fs) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx i; - bool ok; - if (IS_EPSILON_NODE (dfa->nodes[node].type)) - { - re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; - re_node_set *edests = &dfa->edests[node]; - Idx dest_node; - ok = re_node_set_insert (eps_via_nodes, node); - if (BE (! ok, 0)) - return REG_ERROR; - /* Pick up a valid destination, or return REG_MISSING if none - is found. */ - for (dest_node = REG_MISSING, i = 0; i < edests->nelem; ++i) - { - Idx candidate = edests->elems[i]; - if (!re_node_set_contains (cur_nodes, candidate)) - continue; - if (dest_node == REG_MISSING) - dest_node = candidate; - - else - { - /* In order to avoid infinite loop like "(a*)*", return the second - epsilon-transition if the first was already considered. */ - if (re_node_set_contains (eps_via_nodes, dest_node)) - return candidate; - - /* Otherwise, push the second epsilon-transition on the fail stack. */ - else if (fs != NULL - && push_fail_stack (fs, *pidx, candidate, nregs, regs, - eps_via_nodes)) - return REG_ERROR; - - /* We know we are going to exit. */ - break; - } - } - return dest_node; - } - else - { - Idx naccepted = 0; - re_token_type_t type = dfa->nodes[node].type; - -#ifdef RE_ENABLE_I18N - if (dfa->nodes[node].accept_mb) - naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); - else -#endif /* RE_ENABLE_I18N */ - if (type == OP_BACK_REF) - { - Idx subexp_idx = dfa->nodes[node].opr.idx + 1; - naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; - if (fs != NULL) - { - if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) - return REG_MISSING; - else if (naccepted) - { - char *buf = (char *) re_string_get_buffer (&mctx->input); - if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, - naccepted) != 0) - return REG_MISSING; - } - } - - if (naccepted == 0) - { - Idx dest_node; - ok = re_node_set_insert (eps_via_nodes, node); - if (BE (! ok, 0)) - return REG_ERROR; - dest_node = dfa->edests[node].elems[0]; - if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node)) - return dest_node; - } - } - - if (naccepted != 0 - || check_node_accept (mctx, dfa->nodes + node, *pidx)) - { - Idx dest_node = dfa->nexts[node]; - *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; - if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL - || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node))) - return REG_MISSING; - re_node_set_empty (eps_via_nodes); - return dest_node; - } - } - return REG_MISSING; -} - -static reg_errcode_t -internal_function -push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, - Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes) -{ - reg_errcode_t err; - Idx num = fs->num++; - if (fs->num == fs->alloc) - { - struct re_fail_stack_ent_t *new_array; - new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) - * fs->alloc * 2)); - if (new_array == NULL) - return REG_ESPACE; - fs->alloc *= 2; - fs->stack = new_array; - } - fs->stack[num].idx = str_idx; - fs->stack[num].node = dest_node; - fs->stack[num].regs = re_malloc (regmatch_t, nregs); - if (fs->stack[num].regs == NULL) - return REG_ESPACE; - memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); - err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); - return err; -} - -static Idx -internal_function -pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, - regmatch_t *regs, re_node_set *eps_via_nodes) -{ - Idx num = --fs->num; - assert (REG_VALID_INDEX (num)); - *pidx = fs->stack[num].idx; - memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); - re_node_set_free (eps_via_nodes); - re_free (fs->stack[num].regs); - *eps_via_nodes = fs->stack[num].eps_via_nodes; - return fs->stack[num].node; -} - -/* Set the positions where the subexpressions are starts/ends to registers - PMATCH. - Note: We assume that pmatch[0] is already set, and - pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ - -static reg_errcode_t -internal_function -set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, - regmatch_t *pmatch, bool fl_backtrack) -{ - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - Idx idx, cur_node; - re_node_set eps_via_nodes; - struct re_fail_stack_t *fs; - struct re_fail_stack_t fs_body = { 0, 2, NULL }; - regmatch_t *prev_idx_match; - bool prev_idx_match_malloced = false; - -#ifdef DEBUG - assert (nmatch > 1); - assert (mctx->state_log != NULL); -#endif - if (fl_backtrack) - { - fs = &fs_body; - fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); - if (fs->stack == NULL) - return REG_ESPACE; - } - else - fs = NULL; - - cur_node = dfa->init_node; - re_node_set_init_empty (&eps_via_nodes); - - if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) - prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); - else - { - prev_idx_match = re_malloc (regmatch_t, nmatch); - if (prev_idx_match == NULL) - { - free_fail_stack_return (fs); - return REG_ESPACE; - } - prev_idx_match_malloced = true; - } - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - - for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) - { - update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); - - if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) - { - Idx reg_idx; - if (fs) - { - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) - break; - if (reg_idx == nmatch) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); - } - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - } - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOERROR; - } - } - - /* Proceed to next node. */ - cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, - &eps_via_nodes, fs); - - if (BE (! REG_VALID_INDEX (cur_node), 0)) - { - if (BE (cur_node == REG_ERROR, 0)) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - free_fail_stack_return (fs); - return REG_ESPACE; - } - if (fs) - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOMATCH; - } - } - } - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); -} - -static reg_errcode_t -internal_function -free_fail_stack_return (struct re_fail_stack_t *fs) -{ - if (fs) - { - Idx fs_idx; - for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) - { - re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); - re_free (fs->stack[fs_idx].regs); - } - re_free (fs->stack); - } - return REG_NOERROR; -} - -static void -internal_function -update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch) -{ - int type = dfa->nodes[cur_node].type; - if (type == OP_OPEN_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - - /* We are at the first node of this sub expression. */ - if (reg_num < nmatch) - { - pmatch[reg_num].rm_so = cur_idx; - pmatch[reg_num].rm_eo = -1; - } - } - else if (type == OP_CLOSE_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - if (reg_num < nmatch) - { - /* We are at the last node of this sub expression. */ - if (pmatch[reg_num].rm_so < cur_idx) - { - pmatch[reg_num].rm_eo = cur_idx; - /* This is a non-empty match or we are not inside an optional - subexpression. Accept this right away. */ - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - } - else - { - if (dfa->nodes[cur_node].opt_subexp - && prev_idx_match[reg_num].rm_so != -1) - /* We transited through an empty match for an optional - subexpression, like (a?)*, and this is not the subexp's - first match. Copy back the old content of the registers - so that matches of an inner subexpression are undone as - well, like in ((a?))*. */ - memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); - else - /* We completed a subexpression, but it may be part of - an optional one, so do not update PREV_IDX_MATCH. */ - pmatch[reg_num].rm_eo = cur_idx; - } - } - } -} - -/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 - and sift the nodes in each states according to the following rules. - Updated state_log will be wrote to STATE_LOG. - - Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... - 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If `a' isn't the LAST_NODE and `a' can't epsilon transit to - the LAST_NODE, we throw away the node `a'. - 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts - string `s' and transit to `b': - i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node `a'. - 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': - i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node `a'. */ - -#define STATE_NODE_CONTAINS(state,node) \ - ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) - -static reg_errcode_t -internal_function -sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) -{ - reg_errcode_t err; - int null_cnt = 0; - Idx str_idx = sctx->last_str_idx; - re_node_set cur_dest; - -#ifdef DEBUG - assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); -#endif - - /* Build sifted state_log[str_idx]. It has the nodes which can epsilon - transit to the last_node and the last_node itself. */ - err = re_node_set_init_1 (&cur_dest, sctx->last_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* Then check each states in the state_log. */ - while (str_idx > 0) - { - /* Update counters. */ - null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; - if (null_cnt > mctx->max_mb_elem_len) - { - memset (sctx->sifted_states, '\0', - sizeof (re_dfastate_t *) * str_idx); - re_node_set_free (&cur_dest); - return REG_NOERROR; - } - re_node_set_empty (&cur_dest); - --str_idx; - - if (mctx->state_log[str_idx]) - { - err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* Add all the nodes which satisfy the following conditions: - - It can epsilon transit to a node in CUR_DEST. - - It is in CUR_SRC. - And update state_log. */ - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - err = REG_NOERROR; - free_return: - re_node_set_free (&cur_dest); - return err; -} - -static reg_errcode_t -internal_function -build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, re_node_set *cur_dest) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; - Idx i; - - /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. - Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]' - (with the epsilon nodes pre-filtered out). */ - for (i = 0; i < cur_src->nelem; i++) - { - Idx prev_node = cur_src->elems[i]; - int naccepted = 0; - bool ok; - -#ifdef DEBUG - re_token_type_t type = dfa->nodes[prev_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[prev_node].accept_mb) - naccepted = sift_states_iter_mb (mctx, sctx, prev_node, - str_idx, sctx->last_str_idx); -#endif /* RE_ENABLE_I18N */ - - /* We don't check backreferences here. - See update_cur_sifted_state(). */ - if (!naccepted - && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) - && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], - dfa->nexts[prev_node])) - naccepted = 1; - - if (naccepted == 0) - continue; - - if (sctx->limits.nelem) - { - Idx to_idx = str_idx + naccepted; - if (check_dst_limits (mctx, &sctx->limits, - dfa->nexts[prev_node], to_idx, - prev_node, str_idx)) - continue; - } - ok = re_node_set_insert (cur_dest, prev_node); - if (BE (! ok, 0)) - return REG_ESPACE; - } - - return REG_NOERROR; -} - -/* Helper functions. */ - -static reg_errcode_t -internal_function -clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) -{ - Idx top = mctx->state_log_top; - - if (next_state_log_idx >= mctx->input.bufs_len - || (next_state_log_idx >= mctx->input.valid_len - && mctx->input.valid_len < mctx->input.len)) - { - reg_errcode_t err; - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (top < next_state_log_idx) - { - memset (mctx->state_log + top + 1, '\0', - sizeof (re_dfastate_t *) * (next_state_log_idx - top)); - mctx->state_log_top = next_state_log_idx; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, - re_dfastate_t **src, Idx num) -{ - Idx st_idx; - reg_errcode_t err; - for (st_idx = 0; st_idx < num; ++st_idx) - { - if (dst[st_idx] == NULL) - dst[st_idx] = src[st_idx]; - else if (src[st_idx] != NULL) - { - re_node_set merged_set; - err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, - &src[st_idx]->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); - re_node_set_free (&merged_set); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *dest_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? NULL - : &mctx->state_log[str_idx]->nodes); - - if (dest_nodes->nelem == 0) - sctx->sifted_states[str_idx] = NULL; - else - { - if (candidates) - { - /* At first, add the nodes which can epsilon transit to a node in - DEST_NODE. */ - err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Then, check the limitations in the current sift_context. */ - if (sctx->limits.nelem) - { - err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, - mctx->bkref_ents, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - - sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (candidates && mctx->state_log[str_idx]->has_backref) - { - err = sift_states_bkref (mctx, sctx, str_idx, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - reg_errcode_t err = REG_NOERROR; - Idx i; - - re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (!state->inveclosure.alloc) - { - err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < dest_nodes->nelem; i++) - re_node_set_merge (&state->inveclosure, - dfa->inveclosures + dest_nodes->elems[i]); - } - return re_node_set_add_intersect (dest_nodes, candidates, - &state->inveclosure); -} - -static reg_errcode_t -internal_function -sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - Idx ecl_idx; - reg_errcode_t err; - re_node_set *inv_eclosure = dfa->inveclosures + node; - re_node_set except_nodes; - re_node_set_init_empty (&except_nodes); - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (cur_node == node) - continue; - if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) - { - Idx edst1 = dfa->edests[cur_node].elems[0]; - Idx edst2 = ((dfa->edests[cur_node].nelem > 1) - ? dfa->edests[cur_node].elems[1] : REG_MISSING); - if ((!re_node_set_contains (inv_eclosure, edst1) - && re_node_set_contains (dest_nodes, edst1)) - || (REG_VALID_NONZERO_INDEX (edst2) - && !re_node_set_contains (inv_eclosure, edst2) - && re_node_set_contains (dest_nodes, edst2))) - { - err = re_node_set_add_intersect (&except_nodes, candidates, - dfa->inveclosures + cur_node); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&except_nodes); - return err; - } - } - } - } - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (!re_node_set_contains (&except_nodes, cur_node)) - { - Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1; - re_node_set_remove_at (dest_nodes, idx); - } - } - re_node_set_free (&except_nodes); - return REG_NOERROR; -} - -static bool -internal_function -check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx lim_idx, src_pos, dst_pos; - - Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); - Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = mctx->bkref_ents + limits->elems[lim_idx]; - subexp_idx = dfa->nodes[ent->node].opr.idx; - - dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, dst_node, dst_idx, - dst_bkref_idx); - src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, src_node, src_idx, - src_bkref_idx); - - /* In case of: - ( ) - ( ) - ( ) */ - if (src_pos == dst_pos) - continue; /* This is unrelated limitation. */ - else - return true; - } - return false; -} - -static int -internal_function -check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, - Idx subexp_idx, Idx from_node, Idx bkref_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *eclosures = dfa->eclosures + from_node; - Idx node_idx; - - /* Else, we are on the boundary: examine the nodes on the epsilon - closure. */ - for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) - { - Idx node = eclosures->elems[node_idx]; - switch (dfa->nodes[node].type) - { - case OP_BACK_REF: - if (bkref_idx != REG_MISSING) - { - struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; - do - { - Idx dst; - int cpos; - - if (ent->node != node) - continue; - - if (subexp_idx < BITSET_WORD_BITS - && !(ent->eps_reachable_subexps_map - & ((bitset_word_t) 1 << subexp_idx))) - continue; - - /* Recurse trying to reach the OP_OPEN_SUBEXP and - OP_CLOSE_SUBEXP cases below. But, if the - destination node is the same node as the source - node, don't recurse because it would cause an - infinite loop: a regex that exhibits this behavior - is ()\1*\1* */ - dst = dfa->edests[node].elems[0]; - if (dst == from_node) - { - if (boundaries & 1) - return -1; - else /* if (boundaries & 2) */ - return 0; - } - - cpos = - check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - dst, bkref_idx); - if (cpos == -1 /* && (boundaries & 1) */) - return -1; - if (cpos == 0 && (boundaries & 2)) - return 0; - - if (subexp_idx < BITSET_WORD_BITS) - ent->eps_reachable_subexps_map - &= ~((bitset_word_t) 1 << subexp_idx); - } - while (ent++->more); - } - break; - - case OP_OPEN_SUBEXP: - if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) - return -1; - break; - - case OP_CLOSE_SUBEXP: - if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) - return 0; - break; - - default: - break; - } - } - - return (boundaries & 2) ? 1 : 0; -} - -static int -internal_function -check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit, - Idx subexp_idx, Idx from_node, Idx str_idx, - Idx bkref_idx) -{ - struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; - int boundaries; - - /* If we are outside the range of the subexpression, return -1 or 1. */ - if (str_idx < lim->subexp_from) - return -1; - - if (lim->subexp_to < str_idx) - return 1; - - /* If we are within the subexpression, return 0. */ - boundaries = (str_idx == lim->subexp_from); - boundaries |= (str_idx == lim->subexp_to) << 1; - if (boundaries == 0) - return 0; - - /* Else, examine epsilon closure. */ - return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - from_node, bkref_idx); -} - -/* Check the limitations of sub expressions LIMITS, and remove the nodes - which are against limitations from DEST_NODES. */ - -static reg_errcode_t -internal_function -check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates, re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, Idx str_idx) -{ - reg_errcode_t err; - Idx node_idx, lim_idx; - - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = bkref_ents + limits->elems[lim_idx]; - - if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) - continue; /* This is unrelated limitation. */ - - subexp_idx = dfa->nodes[ent->node].opr.idx; - if (ent->subexp_to == str_idx) - { - Idx ops_node = REG_MISSING; - Idx cls_node = REG_MISSING; - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_OPEN_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - ops_node = node; - else if (type == OP_CLOSE_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - cls_node = node; - } - - /* Check the limitation of the open subexpression. */ - /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ - if (REG_VALID_INDEX (ops_node)) - { - err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Check the limitation of the close subexpression. */ - if (REG_VALID_INDEX (cls_node)) - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - if (!re_node_set_contains (dfa->inveclosures + node, - cls_node) - && !re_node_set_contains (dfa->eclosures + node, - cls_node)) - { - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - --node_idx; - } - } - } - else /* (ent->subexp_to != str_idx) */ - { - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) - { - if (subexp_idx != dfa->nodes[node].opr.idx) - continue; - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx node_idx, node; - re_sift_context_t local_sctx; - Idx first_idx = search_cur_bkref_entry (mctx, str_idx); - - if (first_idx == REG_MISSING) - return REG_NOERROR; - - local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ - - for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) - { - Idx enabled_idx; - re_token_type_t type; - struct re_backref_cache_entry *entry; - node = candidates->elems[node_idx]; - type = dfa->nodes[node].type; - /* Avoid infinite loop for the REs like "()\1+". */ - if (node == sctx->last_node && str_idx == sctx->last_str_idx) - continue; - if (type != OP_BACK_REF) - continue; - - entry = mctx->bkref_ents + first_idx; - enabled_idx = first_idx; - do - { - Idx subexp_len; - Idx to_idx; - Idx dst_node; - bool ok; - re_dfastate_t *cur_state; - - if (entry->node != node) - continue; - subexp_len = entry->subexp_to - entry->subexp_from; - to_idx = str_idx + subexp_len; - dst_node = (subexp_len ? dfa->nexts[node] - : dfa->edests[node].elems[0]); - - if (to_idx > sctx->last_str_idx - || sctx->sifted_states[to_idx] == NULL - || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) - || check_dst_limits (mctx, &sctx->limits, node, - str_idx, dst_node, to_idx)) - continue; - - if (local_sctx.sifted_states == NULL) - { - local_sctx = *sctx; - err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.last_node = node; - local_sctx.last_str_idx = str_idx; - ok = re_node_set_insert (&local_sctx.limits, enabled_idx); - if (BE (! ok, 0)) - { - err = REG_ESPACE; - goto free_return; - } - cur_state = local_sctx.sifted_states[str_idx]; - err = sift_states_backward (mctx, &local_sctx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - if (sctx->limited_states != NULL) - { - err = merge_state_array (dfa, sctx->limited_states, - local_sctx.sifted_states, - str_idx + 1); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.sifted_states[str_idx] = cur_state; - re_node_set_remove (&local_sctx.limits, enabled_idx); - - /* mctx->bkref_ents may have changed, reload the pointer. */ - entry = mctx->bkref_ents + enabled_idx; - } - while (enabled_idx++, entry++->more); - } - err = REG_NOERROR; - free_return: - if (local_sctx.sifted_states != NULL) - { - re_node_set_free (&local_sctx.limits); - } - - return err; -} - - -#ifdef RE_ENABLE_I18N -static int -internal_function -sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int naccepted; - /* Check the node can accept `multi byte'. */ - naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); - if (naccepted > 0 && str_idx + naccepted <= max_str_idx && - !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], - dfa->nexts[node_idx])) - /* The node can't accept the `multi byte', or the - destination was already thrown away, then the node - could't accept the current input `multi byte'. */ - naccepted = 0; - /* Otherwise, it is sure that the node could accept - `naccepted' bytes input. */ - return naccepted; -} -#endif /* RE_ENABLE_I18N */ - - -/* Functions for state transition. */ - -/* Return the next state to which the current state STATE will transit by - accepting the current input byte, and update STATE_LOG if necessary. - If STATE can accept a multibyte char/collating element/back reference - update the destination of STATE_LOG. */ - -static re_dfastate_t * -internal_function -transit_state (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - re_dfastate_t **trtable; - unsigned char ch; - -#ifdef RE_ENABLE_I18N - /* If the current state can accept multibyte. */ - if (BE (state->accept_mb, 0)) - { - *err = transit_state_mb (mctx, state); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } -#endif /* RE_ENABLE_I18N */ - - /* Then decide the next state with the single byte. */ -#if 0 - if (0) - /* don't use transition table */ - return transit_state_sb (err, mctx, state); -#endif - - /* Use transition table */ - ch = re_string_fetch_byte (&mctx->input); - for (;;) - { - trtable = state->trtable; - if (BE (trtable != NULL, 1)) - return trtable[ch]; - - trtable = state->word_trtable; - if (BE (trtable != NULL, 1)) - { - unsigned int context; - context - = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return trtable[ch + SBC_MAX]; - else - return trtable[ch]; - } - - if (!build_trtable (mctx->dfa, state)) - { - *err = REG_ESPACE; - return NULL; - } - - /* Retry, we now have a transition table. */ - } -} - -/* Update the state_log if we need */ -re_dfastate_t * -internal_function -merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *next_state) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx cur_idx = re_string_cur_idx (&mctx->input); - - if (cur_idx > mctx->state_log_top) - { - mctx->state_log[cur_idx] = next_state; - mctx->state_log_top = cur_idx; - } - else if (mctx->state_log[cur_idx] == 0) - { - mctx->state_log[cur_idx] = next_state; - } - else - { - re_dfastate_t *pstate; - unsigned int context; - re_node_set next_nodes, *log_nodes, *table_nodes = NULL; - /* If (state_log[cur_idx] != 0), it implies that cur_idx is - the destination of a multibyte char/collating element/ - back reference. Then the next state is the union set of - these destinations and the results of the transition table. */ - pstate = mctx->state_log[cur_idx]; - log_nodes = pstate->entrance_nodes; - if (next_state != NULL) - { - table_nodes = next_state->entrance_nodes; - *err = re_node_set_init_union (&next_nodes, table_nodes, - log_nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - else - next_nodes = *log_nodes; - /* Note: We already add the nodes of the initial state, - then we don't need to add them here. */ - - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - next_state = mctx->state_log[cur_idx] - = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - if (table_nodes != NULL) - re_node_set_free (&next_nodes); - } - - if (BE (dfa->nbackref, 0) && next_state != NULL) - { - /* Check OP_OPEN_SUBEXP in the current state in case that we use them - later. We must check them here, since the back references in the - next state might use them. */ - *err = check_subexp_matching_top (mctx, &next_state->nodes, - cur_idx); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - - /* If the next state has back references. */ - if (next_state->has_backref) - { - *err = transit_state_bkref (mctx, &next_state->nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - next_state = mctx->state_log[cur_idx]; - } - } - - return next_state; -} - -/* Skip bytes in the input that correspond to part of a - multi-byte match, then look in the log for a state - from which to restart matching. */ -static re_dfastate_t * -internal_function -find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) -{ - re_dfastate_t *cur_state; - do - { - Idx max = mctx->state_log_top; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - do - { - if (++cur_str_idx > max) - return NULL; - re_string_skip_bytes (&mctx->input, 1); - } - while (mctx->state_log[cur_str_idx] == NULL); - - cur_state = merge_state_with_log (err, mctx, NULL); - } - while (*err == REG_NOERROR && cur_state == NULL); - return cur_state; -} - -/* Helper functions for transit_state. */ - -/* From the node set CUR_NODES, pick up the nodes whose types are - OP_OPEN_SUBEXP and which have corresponding back references in the regular - expression. And register them to use them later for evaluating the - correspoding back references. */ - -static reg_errcode_t -internal_function -check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx node_idx; - reg_errcode_t err; - - /* TODO: This isn't efficient. - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) - { - Idx node = cur_nodes->elems[node_idx]; - if (dfa->nodes[node].type == OP_OPEN_SUBEXP - && dfa->nodes[node].opr.idx < BITSET_WORD_BITS - && (dfa->used_bkref_map - & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) - { - err = match_ctx_add_subtop (mctx, node, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -#if 0 -/* Return the next state to which the current state STATE will transit by - accepting the current input byte. */ - -static re_dfastate_t * -transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - const re_dfa_t *const dfa = mctx->dfa; - re_node_set next_nodes; - re_dfastate_t *next_state; - Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); - unsigned int context; - - *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) - { - Idx cur_node = state->nodes.elems[node_cnt]; - if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) - { - *err = re_node_set_merge (&next_nodes, - dfa->eclosures + dfa->nexts[cur_node]); - if (BE (*err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return NULL; - } - } - } - context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); - next_state = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - re_node_set_free (&next_nodes); - re_string_skip_bytes (&mctx->input, 1); - return next_state; -} -#endif - -#ifdef RE_ENABLE_I18N -static reg_errcode_t -internal_function -transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - - for (i = 0; i < pstate->nodes.nelem; ++i) - { - re_node_set dest_nodes, *new_nodes; - Idx cur_node_idx = pstate->nodes.elems[i]; - int naccepted; - Idx dest_idx; - unsigned int context; - re_dfastate_t *dest_state; - - if (!dfa->nodes[cur_node_idx].accept_mb) - continue; - - if (dfa->nodes[cur_node_idx].constraint) - { - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input), - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, - context)) - continue; - } - - /* How many bytes the node can accept? */ - naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, - re_string_cur_idx (&mctx->input)); - if (naccepted == 0) - continue; - - /* The node can accepts `naccepted' bytes. */ - dest_idx = re_string_cur_idx (&mctx->input) + naccepted; - mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted - : mctx->max_mb_elem_len); - err = clean_state_log_if_needed (mctx, dest_idx); - if (BE (err != REG_NOERROR, 0)) - return err; -#ifdef DEBUG - assert (dfa->nexts[cur_node_idx] != REG_MISSING); -#endif - new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; - - dest_state = mctx->state_log[dest_idx]; - if (dest_state == NULL) - dest_nodes = *new_nodes; - else - { - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, new_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - context = re_string_context_at (&mctx->input, dest_idx - 1, - mctx->eflags); - mctx->state_log[dest_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - if (dest_state != NULL) - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} -#endif /* RE_ENABLE_I18N */ - -static reg_errcode_t -internal_function -transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - for (i = 0; i < nodes->nelem; ++i) - { - Idx dest_str_idx, prev_nelem, bkc_idx; - Idx node_idx = nodes->elems[i]; - unsigned int context; - const re_token_t *node = dfa->nodes + node_idx; - re_node_set *new_dest_nodes; - - /* Check whether `node' is a backreference or not. */ - if (node->type != OP_BACK_REF) - continue; - - if (node->constraint) - { - context = re_string_context_at (&mctx->input, cur_str_idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - continue; - } - - /* `node' is a backreference. - Check the substring which the substring matched. */ - bkc_idx = mctx->nbkref_ents; - err = get_subexp (mctx, node_idx, cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* And add the epsilon closures (which is `new_dest_nodes') of - the backreference to appropriate state_log. */ -#ifdef DEBUG - assert (dfa->nexts[node_idx] != REG_MISSING); -#endif - for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) - { - Idx subexp_len; - re_dfastate_t *dest_state; - struct re_backref_cache_entry *bkref_ent; - bkref_ent = mctx->bkref_ents + bkc_idx; - if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) - continue; - subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; - new_dest_nodes = (subexp_len == 0 - ? dfa->eclosures + dfa->edests[node_idx].elems[0] - : dfa->eclosures + dfa->nexts[node_idx]); - dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - - bkref_ent->subexp_from); - context = re_string_context_at (&mctx->input, dest_str_idx - 1, - mctx->eflags); - dest_state = mctx->state_log[dest_str_idx]; - prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 - : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add `new_dest_node' to state_log. */ - if (dest_state == NULL) - { - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, new_dest_nodes, - context); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - else - { - re_node_set dest_nodes; - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, - new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&dest_nodes); - goto free_return; - } - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - /* We need to check recursively if the backreference can epsilon - transit. */ - if (subexp_len == 0 - && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) - { - err = check_subexp_matching_top (mctx, new_dest_nodes, - cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - err = transit_state_bkref (mctx, new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - } - } - err = REG_NOERROR; - free_return: - return err; -} - -/* Enumerate all the candidates which the backreference BKREF_NODE can match - at BKREF_STR_IDX, and register them by match_ctx_add_entry(). - Note that we might collect inappropriate candidates here. - However, the cost of checking them strictly here is too high, then we - delay these checking for prune_impossible_nodes(). */ - -static reg_errcode_t -internal_function -get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx subexp_num, sub_top_idx; - const char *buf = (const char *) re_string_get_buffer (&mctx->input); - /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ - Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); - if (cache_idx != REG_MISSING) - { - const struct re_backref_cache_entry *entry - = mctx->bkref_ents + cache_idx; - do - if (entry->node == bkref_node) - return REG_NOERROR; /* We already checked it. */ - while (entry++->more); - } - - subexp_num = dfa->nodes[bkref_node].opr.idx; - - /* For each sub expression */ - for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) - { - reg_errcode_t err; - re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; - re_sub_match_last_t *sub_last; - Idx sub_last_idx, sl_str, bkref_str_off; - - if (dfa->nodes[sub_top->node].opr.idx != subexp_num) - continue; /* It isn't related. */ - - sl_str = sub_top->str_idx; - bkref_str_off = bkref_str_idx; - /* At first, check the last node of sub expressions we already - evaluated. */ - for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) - { - regoff_t sl_str_diff; - sub_last = sub_top->lasts[sub_last_idx]; - sl_str_diff = sub_last->str_idx - sl_str; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_diff > 0) - { - if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) - { - /* Not enough chars for a successful match. */ - if (bkref_str_off + sl_str_diff > mctx->input.len) - break; - - err = clean_state_log_if_needed (mctx, - bkref_str_off - + sl_str_diff); - if (BE (err != REG_NOERROR, 0)) - return err; - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) - /* We don't need to search this sub expression any more. */ - break; - } - bkref_str_off += sl_str_diff; - sl_str += sl_str_diff; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - - /* Reload buf, since the preceding call might have reallocated - the buffer. */ - buf = (const char *) re_string_get_buffer (&mctx->input); - - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (sub_last_idx < sub_top->nlasts) - continue; - if (sub_last_idx > 0) - ++sl_str; - /* Then, search for the other last nodes of the sub expression. */ - for (; sl_str <= bkref_str_idx; ++sl_str) - { - Idx cls_node; - regoff_t sl_str_off; - const re_node_set *nodes; - sl_str_off = sl_str - sub_top->str_idx; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_off > 0) - { - if (BE (bkref_str_off >= mctx->input.valid_len, 0)) - { - /* If we are at the end of the input, we cannot match. */ - if (bkref_str_off >= mctx->input.len) - break; - - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (buf [bkref_str_off++] != buf[sl_str - 1]) - break; /* We don't need to search this sub expression - any more. */ - } - if (mctx->state_log[sl_str] == NULL) - continue; - /* Does this state have a ')' of the sub expression? */ - nodes = &mctx->state_log[sl_str]->nodes; - cls_node = find_subexp_node (dfa, nodes, subexp_num, - OP_CLOSE_SUBEXP); - if (cls_node == REG_MISSING) - continue; /* No. */ - if (sub_top->path == NULL) - { - sub_top->path = calloc (sizeof (state_array_t), - sl_str - sub_top->str_idx + 1); - if (sub_top->path == NULL) - return REG_ESPACE; - } - /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node - in the current context? */ - err = check_arrival (mctx, sub_top->path, sub_top->node, - sub_top->str_idx, cls_node, sl_str, - OP_CLOSE_SUBEXP); - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); - if (BE (sub_last == NULL, 0)) - return REG_ESPACE; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - if (err == REG_NOMATCH) - continue; - } - } - return REG_NOERROR; -} - -/* Helper functions for get_subexp(). */ - -/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. - If it can arrive, register the sub expression expressed with SUB_TOP - and SUB_LAST. */ - -static reg_errcode_t -internal_function -get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str) -{ - reg_errcode_t err; - Idx to_idx; - /* Can the subexpression arrive the back reference? */ - err = check_arrival (mctx, &sub_last->path, sub_last->node, - sub_last->str_idx, bkref_node, bkref_str, - OP_OPEN_SUBEXP); - if (err != REG_NOERROR) - return err; - err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, - sub_last->str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; - return clean_state_log_if_needed (mctx, to_idx); -} - -/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. - Search '(' if FL_OPEN, or search ')' otherwise. - TODO: This function isn't efficient... - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - -static Idx -internal_function -find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) -{ - Idx cls_idx; - for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) - { - Idx cls_node = nodes->elems[cls_idx]; - const re_token_t *node = dfa->nodes + cls_node; - if (node->type == type - && node->opr.idx == subexp_idx) - return cls_node; - } - return REG_MISSING; -} - -/* Check whether the node TOP_NODE at TOP_STR can arrive to the node - LAST_NODE at LAST_STR. We record the path onto PATH since it will be - heavily reused. - Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ - -static reg_errcode_t -internal_function -check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - Idx subexp_num, backup_cur_idx, str_idx, null_cnt; - re_dfastate_t *cur_state = NULL; - re_node_set *cur_nodes, next_nodes; - re_dfastate_t **backup_state_log; - unsigned int context; - - subexp_num = dfa->nodes[top_node].opr.idx; - /* Extend the buffer if we need. */ - if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) - { - re_dfastate_t **new_array; - Idx old_alloc = path->alloc; - Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1; - if (BE (new_alloc < old_alloc, 0) - || BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) - return REG_ESPACE; - new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - path->array = new_array; - path->alloc = new_alloc; - memset (new_array + old_alloc, '\0', - sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); - } - - str_idx = path->next_idx ? path->next_idx : top_str; - - /* Temporary modify MCTX. */ - backup_state_log = mctx->state_log; - backup_cur_idx = mctx->input.cur_idx; - mctx->state_log = path->array; - mctx->input.cur_idx = str_idx; - - /* Setup initial node set. */ - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - if (str_idx == top_str) - { - err = re_node_set_init_1 (&next_nodes, top_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - else - { - cur_state = mctx->state_log[str_idx]; - if (cur_state && cur_state->has_backref) - { - err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - re_node_set_init_empty (&next_nodes); - } - if (str_idx == top_str || (cur_state && cur_state->has_backref)) - { - if (next_nodes.nelem) - { - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - } - - for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) - { - re_node_set_empty (&next_nodes); - if (mctx->state_log[str_idx + 1]) - { - err = re_node_set_merge (&next_nodes, - &mctx->state_log[str_idx + 1]->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - if (cur_state) - { - err = check_arrival_add_next_nodes (mctx, str_idx, - &cur_state->non_eps_nodes, - &next_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - ++str_idx; - if (next_nodes.nelem) - { - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - null_cnt = cur_state == NULL ? null_cnt + 1 : 0; - } - re_node_set_free (&next_nodes); - cur_nodes = (mctx->state_log[last_str] == NULL ? NULL - : &mctx->state_log[last_str]->nodes); - path->next_idx = str_idx; - - /* Fix MCTX. */ - mctx->state_log = backup_state_log; - mctx->input.cur_idx = backup_cur_idx; - - /* Then check the current node set has the node LAST_NODE. */ - if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) - return REG_NOERROR; - - return REG_NOMATCH; -} - -/* Helper functions for check_arrival. */ - -/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them - to NEXT_NODES. - TODO: This function is similar to the functions transit_state*(), - however this function has many additional works. - Can't we unify them? */ - -static reg_errcode_t -internal_function -check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, - re_node_set *cur_nodes, re_node_set *next_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - bool ok; - Idx cur_idx; - reg_errcode_t err = REG_NOERROR; - re_node_set union_set; - re_node_set_init_empty (&union_set); - for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) - { - int naccepted = 0; - Idx cur_node = cur_nodes->elems[cur_idx]; -#ifdef DEBUG - re_token_type_t type = dfa->nodes[cur_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[cur_node].accept_mb) - { - naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, - str_idx); - if (naccepted > 1) - { - re_dfastate_t *dest_state; - Idx next_node = dfa->nexts[cur_node]; - Idx next_idx = str_idx + naccepted; - dest_state = mctx->state_log[next_idx]; - re_node_set_empty (&union_set); - if (dest_state) - { - err = re_node_set_merge (&union_set, &dest_state->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - ok = re_node_set_insert (&union_set, next_node); - if (BE (! ok, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - mctx->state_log[next_idx] = re_acquire_state (&err, dfa, - &union_set); - if (BE (mctx->state_log[next_idx] == NULL - && err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - } -#endif /* RE_ENABLE_I18N */ - if (naccepted - || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) - { - ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); - if (BE (! ok, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - } - } - re_node_set_free (&union_set); - return REG_NOERROR; -} - -/* For all the nodes in CUR_NODES, add the epsilon closures of them to - CUR_NODES, however exclude the nodes which are: - - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. -*/ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, - Idx ex_subexp, int type) -{ - reg_errcode_t err; - Idx idx, outside_node; - re_node_set new_nodes; -#ifdef DEBUG - assert (cur_nodes->nelem); -#endif - err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return err; - /* Create a new node set NEW_NODES with the nodes which are epsilon - closures of the node in CUR_NODES. */ - - for (idx = 0; idx < cur_nodes->nelem; ++idx) - { - Idx cur_node = cur_nodes->elems[idx]; - const re_node_set *eclosure = dfa->eclosures + cur_node; - outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); - if (outside_node == REG_MISSING) - { - /* There are no problematic nodes, just merge them. */ - err = re_node_set_merge (&new_nodes, eclosure); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - else - { - /* There are problematic nodes, re-calculate incrementally. */ - err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - } - re_node_set_free (cur_nodes); - *cur_nodes = new_nodes; - return REG_NOERROR; -} - -/* Helper function for check_arrival_expand_ecl. - Check incrementally the epsilon closure of TARGET, and if it isn't - problematic append it to DST_NODES. */ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, - Idx target, Idx ex_subexp, int type) -{ - Idx cur_node; - for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) - { - bool ok; - - if (dfa->nodes[cur_node].type == type - && dfa->nodes[cur_node].opr.idx == ex_subexp) - { - if (type == OP_CLOSE_SUBEXP) - { - ok = re_node_set_insert (dst_nodes, cur_node); - if (BE (! ok, 0)) - return REG_ESPACE; - } - break; - } - ok = re_node_set_insert (dst_nodes, cur_node); - if (BE (! ok, 0)) - return REG_ESPACE; - if (dfa->edests[cur_node].nelem == 0) - break; - if (dfa->edests[cur_node].nelem == 2) - { - reg_errcode_t err; - err = check_arrival_expand_ecl_sub (dfa, dst_nodes, - dfa->edests[cur_node].elems[1], - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - return err; - } - cur_node = dfa->edests[cur_node].elems[0]; - } - return REG_NOERROR; -} - - -/* For all the back references in the current state, calculate the - destination of the back references by the appropriate entry - in MCTX->BKREF_ENTS. */ - -static reg_errcode_t -internal_function -expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx cur_str, Idx subexp_num, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str); - struct re_backref_cache_entry *ent; - - if (cache_idx_start == REG_MISSING) - return REG_NOERROR; - - restart: - ent = mctx->bkref_ents + cache_idx_start; - do - { - Idx to_idx, next_node; - - /* Is this entry ENT is appropriate? */ - if (!re_node_set_contains (cur_nodes, ent->node)) - continue; /* No. */ - - to_idx = cur_str + ent->subexp_to - ent->subexp_from; - /* Calculate the destination of the back reference, and append it - to MCTX->STATE_LOG. */ - if (to_idx == cur_str) - { - /* The backreference did epsilon transit, we must re-check all the - node in the current state. */ - re_node_set new_dests; - reg_errcode_t err2, err3; - next_node = dfa->edests[ent->node].elems[0]; - if (re_node_set_contains (cur_nodes, next_node)) - continue; - err = re_node_set_init_1 (&new_dests, next_node); - err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); - err3 = re_node_set_merge (cur_nodes, &new_dests); - re_node_set_free (&new_dests); - if (BE (err != REG_NOERROR || err2 != REG_NOERROR - || err3 != REG_NOERROR, 0)) - { - err = (err != REG_NOERROR ? err - : (err2 != REG_NOERROR ? err2 : err3)); - return err; - } - /* TODO: It is still inefficient... */ - goto restart; - } - else - { - re_node_set union_set; - next_node = dfa->nexts[ent->node]; - if (mctx->state_log[to_idx]) - { - bool ok; - if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, - next_node)) - continue; - err = re_node_set_init_copy (&union_set, - &mctx->state_log[to_idx]->nodes); - ok = re_node_set_insert (&union_set, next_node); - if (BE (err != REG_NOERROR || ! ok, 0)) - { - re_node_set_free (&union_set); - err = err != REG_NOERROR ? err : REG_ESPACE; - return err; - } - } - else - { - err = re_node_set_init_1 (&union_set, next_node); - if (BE (err != REG_NOERROR, 0)) - return err; - } - mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); - re_node_set_free (&union_set); - if (BE (mctx->state_log[to_idx] == NULL - && err != REG_NOERROR, 0)) - return err; - } - } - while (ent++->more); - return REG_NOERROR; -} - -/* Build transition table for the state. - Return true if successful. */ - -static bool -internal_function -build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) -{ - reg_errcode_t err; - Idx i, j; - int ch; - bool need_word_trtable = false; - bitset_word_t elem, mask; - bool dests_node_malloced = false; - bool dest_states_malloced = false; - Idx ndests; /* Number of the destination states from `state'. */ - re_dfastate_t **trtable; - re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; - re_node_set follows, *dests_node; - bitset_t *dests_ch; - bitset_t acceptable; - - struct dests_alloc - { - re_node_set dests_node[SBC_MAX]; - bitset_t dests_ch[SBC_MAX]; - } *dests_alloc; - - /* We build DFA states which corresponds to the destination nodes - from `state'. `dests_node[i]' represents the nodes which i-th - destination state contains, and `dests_ch[i]' represents the - characters which i-th destination state accepts. */ - if (__libc_use_alloca (sizeof (struct dests_alloc))) - dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); - else - { - dests_alloc = re_malloc (struct dests_alloc, 1); - if (BE (dests_alloc == NULL, 0)) - return false; - dests_node_malloced = true; - } - dests_node = dests_alloc->dests_node; - dests_ch = dests_alloc->dests_ch; - - /* Initialize transiton table. */ - state->word_trtable = state->trtable = NULL; - - /* At first, group all nodes belonging to `state' into several - destinations. */ - ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); - if (BE (! REG_VALID_NONZERO_INDEX (ndests), 0)) - { - if (dests_node_malloced) - free (dests_alloc); - if (ndests == 0) - { - state->trtable = (re_dfastate_t **) - calloc (sizeof (re_dfastate_t *), SBC_MAX); - return true; - } - return false; - } - - err = re_node_set_alloc (&follows, ndests + 1); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - - /* Avoid arithmetic overflow in size calculation. */ - if (BE ((((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX) - / (3 * sizeof (re_dfastate_t *))) - < ndests), - 0)) - goto out_free; - - if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX - + ndests * 3 * sizeof (re_dfastate_t *))) - dest_states = (re_dfastate_t **) - alloca (ndests * 3 * sizeof (re_dfastate_t *)); - else - { - dest_states = (re_dfastate_t **) - malloc (ndests * 3 * sizeof (re_dfastate_t *)); - if (BE (dest_states == NULL, 0)) - { -out_free: - if (dest_states_malloced) - free (dest_states); - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - if (dests_node_malloced) - free (dests_alloc); - return false; - } - dest_states_malloced = true; - } - dest_states_word = dest_states + ndests; - dest_states_nl = dest_states_word + ndests; - bitset_empty (acceptable); - - /* Then build the states for all destinations. */ - for (i = 0; i < ndests; ++i) - { - Idx next_node; - re_node_set_empty (&follows); - /* Merge the follows of this destination states. */ - for (j = 0; j < dests_node[i].nelem; ++j) - { - next_node = dfa->nexts[dests_node[i].elems[j]]; - if (next_node != REG_MISSING) - { - err = re_node_set_merge (&follows, dfa->eclosures + next_node); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - } - } - dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); - if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - /* If the new state has context constraint, - build appropriate states for these contexts. */ - if (dest_states[i]->has_constraint) - { - dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_WORD); - if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - - if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) - need_word_trtable = true; - - dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_NEWLINE); - if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - } - else - { - dest_states_word[i] = dest_states[i]; - dest_states_nl[i] = dest_states[i]; - } - bitset_merge (acceptable, dests_ch[i]); - } - - if (!BE (need_word_trtable, 0)) - { - /* We don't care about whether the following character is a word - character, or we are in a single-byte character set so we can - discern by looking at the character code: allocate a - 256-entry transition table. */ - trtable = state->trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - if (dfa->word_char[i] & mask) - trtable[ch] = dest_states_word[j]; - else - trtable[ch] = dest_states[j]; - } - } - else - { - /* We care about whether the following character is a word - character, and we are in a multi-byte character set: discern - by looking at the character code: build two 256-entry - transition tables, one starting at trtable[0] and one - starting at trtable[SBC_MAX]. */ - trtable = state->word_trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - trtable[ch] = dest_states[j]; - trtable[ch + SBC_MAX] = dest_states_word[j]; - } - } - - /* new line */ - if (bitset_contain (acceptable, NEWLINE_CHAR)) - { - /* The current state accepts newline character. */ - for (j = 0; j < ndests; ++j) - if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) - { - /* k-th destination accepts newline character. */ - trtable[NEWLINE_CHAR] = dest_states_nl[j]; - if (need_word_trtable) - trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; - /* There must be only one destination which accepts - newline. See group_nodes_into_DFAstates. */ - break; - } - } - - if (dest_states_malloced) - free (dest_states); - - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - - if (dests_node_malloced) - free (dests_alloc); - - return true; -} - -/* Group all nodes belonging to STATE into several destinations. - Then for all destinations, set the nodes belonging to the destination - to DESTS_NODE[i] and set the characters accepted by the destination - to DEST_CH[i]. This function return the number of destinations. */ - -static Idx -internal_function -group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, - re_node_set *dests_node, bitset_t *dests_ch) -{ - reg_errcode_t err; - bool ok; - Idx i, j, k; - Idx ndests; /* Number of the destinations from `state'. */ - bitset_t accepts; /* Characters a node can accept. */ - const re_node_set *cur_nodes = &state->nodes; - bitset_empty (accepts); - ndests = 0; - - /* For all the nodes belonging to `state', */ - for (i = 0; i < cur_nodes->nelem; ++i) - { - re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - /* Enumerate all single byte character this node can accept. */ - if (type == CHARACTER) - bitset_set (accepts, node->opr.c); - else if (type == SIMPLE_BRACKET) - { - bitset_merge (accepts, node->opr.sbcset); - } - else if (type == OP_PERIOD) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - bitset_merge (accepts, dfa->sb_char); - else -#endif - bitset_set_all (accepts); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#ifdef RE_ENABLE_I18N - else if (type == OP_UTF8_PERIOD) - { - if (ASCII_CHARS % BITSET_WORD_BITS == 0) - memset (accepts, -1, ASCII_CHARS / CHAR_BIT); - else - bitset_merge (accepts, utf8_sb_map); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#endif - else - continue; - - /* Check the `accepts' and sift the characters which are not - match it the context. */ - if (constraint) - { - if (constraint & NEXT_NEWLINE_CONSTRAINT) - { - bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); - bitset_empty (accepts); - if (accepts_newline) - bitset_set (accepts, NEWLINE_CHAR); - else - continue; - } - if (constraint & NEXT_ENDBUF_CONSTRAINT) - { - bitset_empty (accepts); - continue; - } - - if (constraint & NEXT_WORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && !node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= dfa->word_char[j]); - if (!any_set) - continue; - } - if (constraint & NEXT_NOTWORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~dfa->word_char[j]); - if (!any_set) - continue; - } - } - - /* Then divide `accepts' into DFA states, or create a new - state. Above, we make sure that accepts is not empty. */ - for (j = 0; j < ndests; ++j) - { - bitset_t intersec; /* Intersection sets, see below. */ - bitset_t remains; - /* Flags, see below. */ - bitset_word_t has_intersec, not_subset, not_consumed; - - /* Optimization, skip if this state doesn't accept the character. */ - if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) - continue; - - /* Enumerate the intersection set of this state and `accepts'. */ - has_intersec = 0; - for (k = 0; k < BITSET_WORDS; ++k) - has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; - /* And skip if the intersection set is empty. */ - if (!has_intersec) - continue; - - /* Then check if this state is a subset of `accepts'. */ - not_subset = not_consumed = 0; - for (k = 0; k < BITSET_WORDS; ++k) - { - not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; - not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; - } - - /* If this state isn't a subset of `accepts', create a - new group state, which has the `remains'. */ - if (not_subset) - { - bitset_copy (dests_ch[ndests], remains); - bitset_copy (dests_ch[j], intersec); - err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - } - - /* Put the position in the current group. */ - ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); - if (BE (! ok, 0)) - goto error_return; - - /* If all characters are consumed, go to next node. */ - if (!not_consumed) - break; - } - /* Some characters remain, create a new group. */ - if (j == ndests) - { - bitset_copy (dests_ch[ndests], accepts); - err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - bitset_empty (accepts); - } - } - return ndests; - error_return: - for (j = 0; j < ndests; ++j) - re_node_set_free (dests_node + j); - return REG_MISSING; -} - -#ifdef RE_ENABLE_I18N -/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. - Return the number of the bytes the node accepts. - STR_IDX is the current index of the input string. - - This function handles the nodes which can accept one character, or - one collating element like '.', '[a-z]', opposite to the other nodes - can only accept one byte. */ - -static int -internal_function -check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx str_idx) -{ - const re_token_t *node = dfa->nodes + node_idx; - int char_len, elem_len; - Idx i; - - if (BE (node->type == OP_UTF8_PERIOD, 0)) - { - unsigned char c = re_string_byte_at (input, str_idx), d; - if (BE (c < 0xc2, 1)) - return 0; - - if (str_idx + 2 > input->len) - return 0; - - d = re_string_byte_at (input, str_idx + 1); - if (c < 0xe0) - return (d < 0x80 || d > 0xbf) ? 0 : 2; - else if (c < 0xf0) - { - char_len = 3; - if (c == 0xe0 && d < 0xa0) - return 0; - } - else if (c < 0xf8) - { - char_len = 4; - if (c == 0xf0 && d < 0x90) - return 0; - } - else if (c < 0xfc) - { - char_len = 5; - if (c == 0xf8 && d < 0x88) - return 0; - } - else if (c < 0xfe) - { - char_len = 6; - if (c == 0xfc && d < 0x84) - return 0; - } - else - return 0; - - if (str_idx + char_len > input->len) - return 0; - - for (i = 1; i < char_len; ++i) - { - d = re_string_byte_at (input, str_idx + i); - if (d < 0x80 || d > 0xbf) - return 0; - } - return char_len; - } - - char_len = re_string_char_size_at (input, str_idx); - if (node->type == OP_PERIOD) - { - if (char_len <= 1) - return 0; - /* FIXME: I don't think this if is needed, as both '\n' - and '\0' are char_len == 1. */ - /* '.' accepts any one character except the following two cases. */ - if ((!(dfa->syntax & RE_DOT_NEWLINE) && - re_string_byte_at (input, str_idx) == '\n') || - ((dfa->syntax & RE_DOT_NOT_NULL) && - re_string_byte_at (input, str_idx) == '\0')) - return 0; - return char_len; - } - - elem_len = re_string_elem_size_at (input, str_idx); - if ((elem_len <= 1 && char_len <= 1) || char_len == 0) - return 0; - - if (node->type == COMPLEX_BRACKET) - { - const re_charset_t *cset = node->opr.mbcset; -# ifdef _LIBC - const unsigned char *pin - = ((const unsigned char *) re_string_get_buffer (input) + str_idx); - Idx j; - uint32_t nrules; -# endif /* _LIBC */ - int match_len = 0; - wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) - ? re_string_wchar_at (input, str_idx) : 0); - - /* match with multibyte character? */ - for (i = 0; i < cset->nmbchars; ++i) - if (wc == cset->mbchars[i]) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - /* match with character_class? */ - for (i = 0; i < cset->nchar_classes; ++i) - { - wctype_t wt = cset->char_classes[i]; - if (__iswctype (wc, wt)) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - -# ifdef _LIBC - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - unsigned int in_collseq = 0; - const int32_t *table, *indirect; - const unsigned char *weights, *extra; - const char *collseqwc; - int32_t idx; - /* This #include defines a local function! */ -# include - - /* match with collating_symbol? */ - if (cset->ncoll_syms) - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - for (i = 0; i < cset->ncoll_syms; ++i) - { - const unsigned char *coll_sym = extra + cset->coll_syms[i]; - /* Compare the length of input collating element and - the length of current collating element. */ - if (*coll_sym != elem_len) - continue; - /* Compare each bytes. */ - for (j = 0; j < *coll_sym; j++) - if (pin[j] != coll_sym[1 + j]) - break; - if (j == *coll_sym) - { - /* Match if every bytes is equal. */ - match_len = j; - goto check_node_accept_bytes_match; - } - } - - if (cset->nranges) - { - if (elem_len <= char_len) - { - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - in_collseq = __collseq_table_lookup (collseqwc, wc); - } - else - in_collseq = find_collation_sequence_value (pin, elem_len); - } - /* match with range expression? */ - for (i = 0; i < cset->nranges; ++i) - if (cset->range_starts[i] <= in_collseq - && in_collseq <= cset->range_ends[i]) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - - /* match with equivalence_class? */ - if (cset->nequiv_classes) - { - const unsigned char *cp = pin; - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - idx = findidx (&cp); - if (idx > 0) - for (i = 0; i < cset->nequiv_classes; ++i) - { - int32_t equiv_class_idx = cset->equiv_classes[i]; - size_t weight_len = weights[idx]; - if (weight_len == weights[equiv_class_idx]) - { - Idx cnt = 0; - while (cnt <= weight_len - && (weights[equiv_class_idx + 1 + cnt] - == weights[idx + 1 + cnt])) - ++cnt; - if (cnt > weight_len) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - } - } - } - } - else -# endif /* _LIBC */ - { - /* match with range expression? */ -#if __GNUC__ >= 2 - wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; -#else - wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - cmp_buf[2] = wc; -#endif - for (i = 0; i < cset->nranges; ++i) - { - cmp_buf[0] = cset->range_starts[i]; - cmp_buf[4] = cset->range_ends[i]; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - } - check_node_accept_bytes_match: - if (!cset->non_match) - return match_len; - else - { - if (match_len > 0) - return 0; - else - return (elem_len > char_len) ? elem_len : char_len; - } - } - return 0; -} - -# ifdef _LIBC -static unsigned int -internal_function -find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) -{ - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules == 0) - { - if (mbs_len == 1) - { - /* No valid character. Match it as a single byte character. */ - const unsigned char *collseq = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - return collseq[mbs[0]]; - } - return UINT_MAX; - } - else - { - int32_t idx; - const unsigned char *extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - int32_t extrasize = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; - - for (idx = 0; idx < extrasize;) - { - int mbs_cnt; - bool found = false; - int32_t elem_mbs_len; - /* Skip the name of collating element name. */ - idx = idx + extra[idx] + 1; - elem_mbs_len = extra[idx++]; - if (mbs_len == elem_mbs_len) - { - for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) - if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) - break; - if (mbs_cnt == elem_mbs_len) - /* Found the entry. */ - found = true; - } - /* Skip the byte sequence of the collating element. */ - idx += elem_mbs_len; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (extra[idx] + 1); - /* If we found the entry, return the sequence value. */ - if (found) - return *(uint32_t *) (extra + idx); - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - } - return UINT_MAX; - } -} -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ - -/* Check whether the node accepts the byte which is IDX-th - byte of the INPUT. */ - -static bool -internal_function -check_node_accept (const re_match_context_t *mctx, const re_token_t *node, - Idx idx) -{ - unsigned char ch; - ch = re_string_byte_at (&mctx->input, idx); - switch (node->type) - { - case CHARACTER: - if (node->opr.c != ch) - return false; - break; - - case SIMPLE_BRACKET: - if (!bitset_contain (node->opr.sbcset, ch)) - return false; - break; - -#ifdef RE_ENABLE_I18N - case OP_UTF8_PERIOD: - if (ch >= ASCII_CHARS) - return false; - /* FALLTHROUGH */ -#endif - case OP_PERIOD: - if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) - || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) - return false; - break; - - default: - return false; - } - - if (node->constraint) - { - /* The node has constraints. Check whether the current context - satisfies the constraints. */ - unsigned int context = re_string_context_at (&mctx->input, idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - return false; - } - - return true; -} - -/* Extend the buffers, if the buffers have run out. */ - -static reg_errcode_t -internal_function -extend_buffers (re_match_context_t *mctx) -{ - reg_errcode_t ret; - re_string_t *pstr = &mctx->input; - - /* Avoid overflow. */ - if (BE (SIZE_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0)) - return REG_ESPACE; - - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - if (mctx->state_log != NULL) - { - /* And double the length of state_log. */ - /* XXX We have no indication of the size of this buffer. If this - allocation fail we have no indication that the state_log array - does not have the right size. */ - re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, - pstr->bufs_len + 1); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->state_log = new_array; - } - - /* Then reconstruct the buffers. */ - if (pstr->icase) - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - } - return REG_NOERROR; -} - - -/* Functions for matching context. */ - -/* Initialize MCTX. */ - -static reg_errcode_t -internal_function -match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) -{ - mctx->eflags = eflags; - mctx->match_last = REG_MISSING; - if (n > 0) - { - /* Avoid overflow. */ - size_t max_object_size = - MAX (sizeof (struct re_backref_cache_entry), - sizeof (re_sub_match_top_t *)); - if (BE (SIZE_MAX / max_object_size < n, 0)) - return REG_ESPACE; - - mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); - mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); - if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) - return REG_ESPACE; - } - /* Already zero-ed by the caller. - else - mctx->bkref_ents = NULL; - mctx->nbkref_ents = 0; - mctx->nsub_tops = 0; */ - mctx->abkref_ents = n; - mctx->max_mb_elem_len = 1; - mctx->asub_tops = n; - return REG_NOERROR; -} - -/* Clean the entries which depend on the current input in MCTX. - This function must be invoked when the matcher changes the start index - of the input, or changes the input string. */ - -static void -internal_function -match_ctx_clean (re_match_context_t *mctx) -{ - Idx st_idx; - for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) - { - Idx sl_idx; - re_sub_match_top_t *top = mctx->sub_tops[st_idx]; - for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) - { - re_sub_match_last_t *last = top->lasts[sl_idx]; - re_free (last->path.array); - re_free (last); - } - re_free (top->lasts); - if (top->path) - { - re_free (top->path->array); - re_free (top->path); - } - free (top); - } - - mctx->nsub_tops = 0; - mctx->nbkref_ents = 0; -} - -/* Free all the memory associated with MCTX. */ - -static void -internal_function -match_ctx_free (re_match_context_t *mctx) -{ - /* First, free all the memory associated with MCTX->SUB_TOPS. */ - match_ctx_clean (mctx); - re_free (mctx->sub_tops); - re_free (mctx->bkref_ents); -} - -/* Add a new backreference entry to MCTX. - Note that we assume that caller never call this function with duplicate - entry, and call with STR_IDX which isn't smaller than any existing entry. -*/ - -static reg_errcode_t -internal_function -match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, - Idx to) -{ - if (mctx->nbkref_ents >= mctx->abkref_ents) - { - struct re_backref_cache_entry* new_entry; - new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, - mctx->abkref_ents * 2); - if (BE (new_entry == NULL, 0)) - { - re_free (mctx->bkref_ents); - return REG_ESPACE; - } - mctx->bkref_ents = new_entry; - memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', - sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); - mctx->abkref_ents *= 2; - } - if (mctx->nbkref_ents > 0 - && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) - mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; - - mctx->bkref_ents[mctx->nbkref_ents].node = node; - mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; - mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; - mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; - - /* This is a cache that saves negative results of check_dst_limits_calc_pos. - If bit N is clear, means that this entry won't epsilon-transition to - an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If - it is set, check_dst_limits_calc_pos_1 will recurse and try to find one - such node. - - A backreference does not epsilon-transition unless it is empty, so set - to all zeros if FROM != TO. */ - mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map - = (from == to ? -1 : 0); - - mctx->bkref_ents[mctx->nbkref_ents++].more = 0; - if (mctx->max_mb_elem_len < to - from) - mctx->max_mb_elem_len = to - from; - return REG_NOERROR; -} - -/* Return the first entry with the same str_idx, or REG_MISSING if none is - found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ - -static Idx -internal_function -search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) -{ - Idx left, right, mid, last; - last = right = mctx->nbkref_ents; - for (left = 0; left < right;) - { - mid = (left + right) / 2; - if (mctx->bkref_ents[mid].str_idx < str_idx) - left = mid + 1; - else - right = mid; - } - if (left < last && mctx->bkref_ents[left].str_idx == str_idx) - return left; - else - return REG_MISSING; -} - -/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches - at STR_IDX. */ - -static reg_errcode_t -internal_function -match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) -{ -#ifdef DEBUG - assert (mctx->sub_tops != NULL); - assert (mctx->asub_tops > 0); -#endif - if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) - { - Idx new_asub_tops = mctx->asub_tops * 2; - re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, - re_sub_match_top_t *, - new_asub_tops); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops = new_array; - mctx->asub_tops = new_asub_tops; - } - mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); - if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops[mctx->nsub_tops]->node = node; - mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; - return REG_NOERROR; -} - -/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches - at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ - -static re_sub_match_last_t * -internal_function -match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) -{ - re_sub_match_last_t *new_entry; - if (BE (subtop->nlasts == subtop->alasts, 0)) - { - Idx new_alasts = 2 * subtop->alasts + 1; - re_sub_match_last_t **new_array = re_realloc (subtop->lasts, - re_sub_match_last_t *, - new_alasts); - if (BE (new_array == NULL, 0)) - return NULL; - subtop->lasts = new_array; - subtop->alasts = new_alasts; - } - new_entry = calloc (1, sizeof (re_sub_match_last_t)); - if (BE (new_entry != NULL, 1)) - { - subtop->lasts[subtop->nlasts] = new_entry; - new_entry->node = node; - new_entry->str_idx = str_idx; - ++subtop->nlasts; - } - return new_entry; -} - -static void -internal_function -sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx) -{ - sctx->sifted_states = sifted_sts; - sctx->limited_states = limited_sts; - sctx->last_node = last_node; - sctx->last_str_idx = last_str_idx; - re_node_set_init_empty (&sctx->limits); -} diff --git a/src/bin/m4/lib/sigprocmask.c b/src/bin/m4/lib/sigprocmask.c deleted file mode 100644 index c38c7e32fd..0000000000 --- a/src/bin/m4/lib/sigprocmask.c +++ /dev/null @@ -1,192 +0,0 @@ -/* POSIX compatible signal blocking. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "sigprocmask.h" - -#include -#include -#include - -/* We assume that a platform without POSIX signal blocking functions also - does not have the POSIX sigaction() function, only the signal() function. - This is true for Woe32 platforms. */ - -/* A signal handler. */ -typedef void (*handler_t) (int signal); - -int -sigismember (const sigset_t *set, int sig) -{ - if (sig >= 0 && sig < NSIG) - return (*set >> sig) & 1; - else - return 0; -} - -int -sigemptyset (sigset_t *set) -{ - *set = 0; - return 0; -} - -int -sigaddset (sigset_t *set, int sig) -{ - if (sig >= 0 && sig < NSIG) - { - *set |= 1U << sig; - return 0; - } - else - { - errno = EINVAL; - return -1; - } -} - -int -sigdelset (sigset_t *set, int sig) -{ - if (sig >= 0 && sig < NSIG) - { - *set &= ~(1U << sig); - return 0; - } - else - { - errno = EINVAL; - return -1; - } -} - -int -sigfillset (sigset_t *set) -{ - *set = (2U << (NSIG - 1)) - 1; - return 0; -} - -/* Set of currently blocked signals. */ -static sigset_t blocked_set /* = 0 */; - -/* Set of currently blocked and pending signals. */ -static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */; - -/* Signal handler that is installed for blocked signals. */ -static void -blocked_handler (int sig) -{ - if (sig >= 0 && sig < NSIG) - pending_array[sig] = 1; -} - -int -sigpending (sigset_t *set) -{ - sigset_t pending = 0; - int sig; - - for (sig = 0; sig < NSIG; sig++) - if (pending_array[sig]) - pending |= 1U << sig; - return pending; -} - -/* The previous signal handlers. - Only the array elements corresponding to blocked signals are relevant. */ -static handler_t old_handlers[NSIG]; - -int -sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) -{ - if (old_set != NULL) - *old_set = blocked_set; - - if (set != NULL) - { - sigset_t new_blocked_set; - sigset_t to_unblock; - sigset_t to_block; - - switch (operation) - { - case SIG_BLOCK: - new_blocked_set = blocked_set | *set; - break; - case SIG_SETMASK: - new_blocked_set = *set; - break; - case SIG_UNBLOCK: - new_blocked_set = blocked_set & ~*set; - break; - default: - errno = EINVAL; - return -1; - } - to_unblock = blocked_set & ~new_blocked_set; - to_block = new_blocked_set & ~blocked_set; - - if (to_block != 0) - { - int sig; - - for (sig = 0; sig < NSIG; sig++) - if ((to_block >> sig) & 1) - { - pending_array[sig] = 0; - if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR) - blocked_set |= 1U << sig; - } - } - - if (to_unblock != 0) - { - sig_atomic_t received[NSIG]; - int sig; - - for (sig = 0; sig < NSIG; sig++) - if ((to_unblock >> sig) & 1) - { - if (signal (sig, old_handlers[sig]) != blocked_handler) - /* The application changed a signal handler while the signal - was blocked. We don't support this. */ - abort (); - received[sig] = pending_array[sig]; - blocked_set &= ~(1U << sig); - pending_array[sig] = 0; - } - else - received[sig] = 0; - - for (sig = 0; sig < NSIG; sig++) - if (received[sig]) - { - #if HAVE_RAISE - raise (sig); - #else - kill (getpid (), sig); - #endif - } - } - } - return 0; -} diff --git a/src/bin/m4/lib/sigprocmask.h b/src/bin/m4/lib/sigprocmask.h deleted file mode 100644 index d31c365a30..0000000000 --- a/src/bin/m4/lib/sigprocmask.h +++ /dev/null @@ -1,69 +0,0 @@ -/* POSIX compatible signal blocking. - Copyright (C) 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2006. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#if ! HAVE_POSIX_SIGNALBLOCKING - -/* Mingw defines sigset_t not in , but in . */ -# include - -# include "verify.h" - -/* Maximum signal number + 1. */ -# ifndef NSIG -# define NSIG 32 -# endif - -/* This code supports only 32 signals. */ -verify (NSIG <= 32); - -/* A set or mask of signals. */ -# if !HAVE_SIGSET_T -typedef unsigned int sigset_t; -# endif - -/* Test whether a given signal is contained in a signal set. */ -extern int sigismember (const sigset_t *set, int sig); - -/* Initialize a signal set to the empty set. */ -extern int sigemptyset (sigset_t *set); - -/* Add a signal to a signal set. */ -extern int sigaddset (sigset_t *set, int sig); - -/* Remove a signal from a signal set. */ -extern int sigdelset (sigset_t *set, int sig); - -/* Fill a signal set with all possible signals. */ -extern int sigfillset (sigset_t *set); - -/* Return the set of those blocked signals that are pending. */ -extern int sigpending (sigset_t *set); - -/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET. - Then, if SET is not NULL, affect the current set of blocked signals by - combining it with *SET as indicated in OPERATION. - In this implementation, you are not allowed to change a signal handler - while the signal is blocked. */ -# define SIG_BLOCK 0 /* blocked_set = blocked_set | *set; */ -# define SIG_SETMASK 1 /* blocked_set = *set; */ -# define SIG_UNBLOCK 2 /* blocked_set = blocked_set & ~*set; */ -extern int sigprocmask (int operation, const sigset_t *set, sigset_t *old_set); - -#endif diff --git a/src/bin/m4/lib/size_max.h b/src/bin/m4/lib/size_max.h deleted file mode 100644 index ed0bc13771..0000000000 --- a/src/bin/m4/lib/size_max.h +++ /dev/null @@ -1,31 +0,0 @@ -/* size_max.h -- declare SIZE_MAX through system headers - Copyright (C) 2005-2006 Free Software Foundation, Inc. - Written by Simon Josefsson. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef GNULIB_SIZE_MAX_H -#define GNULIB_SIZE_MAX_H - -/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */ -# include -/* Get SIZE_MAX declaration on systems like glibc 2. */ -# if HAVE_STDINT_H -# include -# endif -/* On systems where these include files don't define it, SIZE_MAX is defined - in config.h. */ - -#endif /* GNULIB_SIZE_MAX_H */ diff --git a/src/bin/m4/lib/stat_.h b/src/bin/m4/lib/stat_.h deleted file mode 100644 index cbf5ac00ac..0000000000 --- a/src/bin/m4/lib/stat_.h +++ /dev/null @@ -1,275 +0,0 @@ -/* Provide a more complete sys/stat header file. - Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ - -#ifndef _gl_SYS_STAT_H -#define _gl_SYS_STAT_H - -/* This file is supposed to be used on platforms where is - incomplete. It is intended to provide definitions and prototypes - needed by an application. Start with what the system provides. */ -#include @ABSOLUTE_SYS_STAT_H@ - -#ifndef S_IFMT -# define S_IFMT 0170000 -#endif - -#if STAT_MACROS_BROKEN -# undef S_ISBLK -# undef S_ISCHR -# undef S_ISDIR -# undef S_ISFIFO -# undef S_ISLNK -# undef S_ISNAM -# undef S_ISMPB -# undef S_ISMPC -# undef S_ISNWK -# undef S_ISREG -# undef S_ISSOCK -#endif - -#ifndef S_ISBLK -# ifdef S_IFBLK -# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -# else -# define S_ISBLK(m) 0 -# endif -#endif - -#ifndef S_ISCHR -# ifdef S_IFCHR -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -# else -# define S_ISCHR(m) 0 -# endif -#endif - -#ifndef S_ISDIR -# ifdef S_IFDIR -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -# else -# define S_ISDIR(m) 0 -# endif -#endif - -#ifndef S_ISDOOR /* Solaris 2.5 and up */ -# define S_ISDOOR(m) 0 -#endif - -#ifndef S_ISFIFO -# ifdef S_IFIFO -# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) -# else -# define S_ISFIFO(m) 0 -# endif -#endif - -#ifndef S_ISLNK -# ifdef S_IFLNK -# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -# else -# define S_ISLNK(m) 0 -# endif -#endif - -#ifndef S_ISMPB /* V7 */ -# ifdef S_IFMPB -# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) -# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) -# else -# define S_ISMPB(m) 0 -# define S_ISMPC(m) 0 -# endif -#endif - -#ifndef S_ISNAM /* Xenix */ -# ifdef S_IFNAM -# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) -# else -# define S_ISNAM(m) 0 -# endif -#endif - -#ifndef S_ISNWK /* HP/UX */ -# ifdef S_IFNWK -# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) -# else -# define S_ISNWK(m) 0 -# endif -#endif - -#ifndef S_ISPORT /* Solaris 10 and up */ -# define S_ISPORT(m) 0 -#endif - -#ifndef S_ISREG -# ifdef S_IFREG -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -# else -# define S_ISREG(m) 0 -# endif -#endif - -#ifndef S_ISSOCK -# ifdef S_IFSOCK -# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -# else -# define S_ISSOCK(m) 0 -# endif -#endif - - -#ifndef S_TYPEISMQ -# define S_TYPEISMQ(p) 0 -#endif - -#ifndef S_TYPEISTMO -# define S_TYPEISTMO(p) 0 -#endif - - -#ifndef S_TYPEISSEM -# ifdef S_INSEM -# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) -# else -# define S_TYPEISSEM(p) 0 -# endif -#endif - -#ifndef S_TYPEISSHM -# ifdef S_INSHD -# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) -# else -# define S_TYPEISSHM(p) 0 -# endif -#endif - -/* high performance ("contiguous data") */ -#ifndef S_ISCTG -# define S_ISCTG(p) 0 -#endif - -/* Cray DMF (data migration facility): off line, with data */ -#ifndef S_ISOFD -# define S_ISOFD(p) 0 -#endif - -/* Cray DMF (data migration facility): off line, with no data */ -#ifndef S_ISOFL -# define S_ISOFL(p) 0 -#endif - -/* 4.4BSD whiteout */ -#ifndef S_ISWHT -# define S_ISWHT(m) 0 -#endif - -/* If any of the following are undefined, - define them to their de facto standard values. */ -#if !S_ISUID -# define S_ISUID 04000 -#endif -#if !S_ISGID -# define S_ISGID 02000 -#endif - -/* S_ISVTX is a common extension to POSIX. */ -#ifndef S_ISVTX -# define S_ISVTX 01000 -#endif - -#if !S_IRUSR && S_IREAD -# define S_IRUSR S_IREAD -#endif -#if !S_IRUSR -# define S_IRUSR 00400 -#endif -#if !S_IRGRP -# define S_IRGRP (S_IRUSR >> 3) -#endif -#if !S_IROTH -# define S_IROTH (S_IRUSR >> 6) -#endif - -#if !S_IWUSR && S_IWRITE -# define S_IWUSR S_IWRITE -#endif -#if !S_IWUSR -# define S_IWUSR 00200 -#endif -#if !S_IWGRP -# define S_IWGRP (S_IWUSR >> 3) -#endif -#if !S_IWOTH -# define S_IWOTH (S_IWUSR >> 6) -#endif - -#if !S_IXUSR && S_IEXEC -# define S_IXUSR S_IEXEC -#endif -#if !S_IXUSR -# define S_IXUSR 00100 -#endif -#if !S_IXGRP -# define S_IXGRP (S_IXUSR >> 3) -#endif -#if !S_IXOTH -# define S_IXOTH (S_IXUSR >> 6) -#endif - -#if !S_IRWXU -# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) -#endif -#if !S_IRWXG -# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#endif -#if !S_IRWXO -# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#endif - -/* S_IXUGO is a common extension to POSIX. */ -#if !S_IXUGO -# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) -#endif - -#ifndef S_IRWXUGO -# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) -#endif - -/* mingw does not support symlinks, therefore it does not have lstat. But - without links, stat does just fine. */ -#if ! HAVE_LSTAT -# define lstat stat -#endif - -/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. - Additionally, it declares _mkdir (and depending on compile flags, an - alias mkdir), only in the nonstandard io.h. */ -#if ! HAVE_DECL_MKDIR && HAVE_IO_H -# include - -static inline int -rpl_mkdir (char const *name, mode_t mode) -{ - return _mkdir (name); -} - -# define mkdir rpl_mkdir -#endif - -#endif /* _gl_SYS_STAT_H */ diff --git a/src/bin/m4/lib/stdbool_.h b/src/bin/m4/lib/stdbool_.h deleted file mode 100644 index db08b7a9dd..0000000000 --- a/src/bin/m4/lib/stdbool_.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2001. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _STDBOOL_H -#define _STDBOOL_H - -/* ISO C 99 for platforms that lack it. */ - -/* Usage suggestions: - - Programs that use should be aware of some limitations - and standards compliance issues. - - Standards compliance: - - - must be #included before 'bool', 'false', 'true' - can be used. - - - You cannot assume that sizeof (bool) == 1. - - - Programs should not undefine the macros bool, true, and false, - as C99 lists that as an "obsolescent feature". - - Limitations of this substitute, when used in a C89 environment: - - - must be #included before the '_Bool' type can be used. - - - You cannot assume that _Bool is a typedef; it might be a macro. - - - In C99, casts and automatic conversions to '_Bool' or 'bool' are - performed in such a way that every nonzero value gets converted - to 'true', and zero gets converted to 'false'. This doesn't work - with this substitute. With this substitute, only the values 0 and 1 - give the expected result when converted to _Bool' or 'bool'. - - Also, it is suggested that programs use 'bool' rather than '_Bool'; - this isn't required, but 'bool' is more common. */ - - -/* 7.16. Boolean type and values */ - -/* BeOS already #defines false 0, true 1. We use the same - definitions below, but temporarily we have to #undef them. */ -#if (defined(__BEOS__) || defined(__HAIKU__)) -# include /* defines bool but not _Bool */ -# undef false -# undef true -#endif - -/* For the sake of symbolic names in gdb, we define true and false as - enum constants, not only as macros. - It is tempting to write - typedef enum { false = 0, true = 1 } _Bool; - so that gdb prints values of type 'bool' symbolically. But if we do - this, values of type '_Bool' may promote to 'int' or 'unsigned int' - (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int' - (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the - enum; this ensures that '_Bool' promotes to 'int'. */ -#if defined __cplusplus || (defined(__BEOS__) || defined(__HAIKU__)) - /* A compiler known to have 'bool'. */ - /* If the compiler already has both 'bool' and '_Bool', we can assume they - are the same types. */ -# if !@HAVE__BOOL@ -typedef bool _Bool; -# endif -#else -# if !defined __GNUC__ - /* If @HAVE__BOOL@: - Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when - the built-in _Bool type is used. See - http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html - http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html - http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html - Similar bugs are likely with other compilers as well; this file - wouldn't be used if was working. - So we override the _Bool type. - If !@HAVE__BOOL@: - Need to define _Bool ourselves. As 'signed char' or as an enum type? - Use of a typedef, with SunPRO C, leads to a stupid - "warning: _Bool is a keyword in ISO C99". - Use of an enum type, with IRIX cc, leads to a stupid - "warning(1185): enumerated type mixed with another type". - The only benefit of the enum type, debuggability, is not important - with these compilers. So use 'signed char' and no typedef. */ -# define _Bool signed char -enum { false = 0, true = 1 }; -# else - /* With this compiler, trust the _Bool type if the compiler has it. */ -# if !@HAVE__BOOL@ -typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; -# endif -# endif -#endif -#define bool _Bool - -/* The other macros must be usable in preprocessor directives. */ -#define false 0 -#define true 1 -#define __bool_true_false_are_defined 1 - -#endif /* _STDBOOL_H */ diff --git a/src/bin/m4/lib/stdint_.h b/src/bin/m4/lib/stdint_.h deleted file mode 100644 index a4f9a4cf7b..0000000000 --- a/src/bin/m4/lib/stdint_.h +++ /dev/null @@ -1,493 +0,0 @@ -/* Copyright (C) 2001-2002, 2004-2006 Free Software Foundation, Inc. - Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. - This file is part of gnulib. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_STDINT_H -#define _GL_STDINT_H - -/* - * ISO C 99 for platforms that lack it. - * - */ - -/* Get those types that are already defined in other system include - files, so that we can "#define int8_t signed char" below without - worrying about a later system include file containing a "typedef - signed char int8_t;" that will get messed up by our macro. Our - macros should all be consistent with the system versions, except - for the "fast" types and macros, which we recommend against using - in public interfaces due to compiler differences. */ - -#if @HAVE_STDINT_H@ -# if defined __sgi && ! defined __c99 - /* Bypass IRIX's if in C89 mode, since it merely annoys users - with "This header file is to be used only for c99 mode compilations" - diagnostics. */ -# define __STDINT_H__ -# endif - /* Other systems may have an incomplete or buggy . - Include it before , since any "#include " - in would reinclude us, skipping our contents because - _GL_STDINT_H is defined. */ -# include @ABSOLUTE_STDINT_H@ -#endif - -/* defines some of the stdint.h types as well, on glibc, - IRIX 6.5, and OpenBSD 3.8 (via ). - AIX 5.2 isn't needed and causes troubles. - MacOS X 10.4.6 includes (which is us), but - relies on the system definitions, so include - after @ABSOLUTE_STDINT_H@. */ -#if @HAVE_SYS_TYPES_H@ && ! defined _AIX -# include -#endif - -/* Get LONG_MIN, LONG_MAX, ULONG_MAX. */ -#include - -#if @HAVE_INTTYPES_H@ - /* In OpenBSD 3.8, includes , which defines - int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. - also defines intptr_t and uintptr_t. */ -# define _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H -# include -# undef _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H -#elif @HAVE_SYS_INTTYPES_H@ - /* Solaris 7 has the types except the *_fast*_t types, and - the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ -# include -#endif - -#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ - /* Linux libc4 >= 4.6.7 and libc5 have a that defines - int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is - included by . */ -# include -#endif - -#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS - -/* Get WCHAR_MIN, WCHAR_MAX. */ -# if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) - /* BSD/OS 4.1 has a bug: and must be included before - . */ -# include -# include -# include -# endif - -#endif - -/* Minimum and maximum values for a integer type under the usual assumption. - Return an unspecified value if BITS == 0, adding a check to pacify - picky compilers. */ - -#define _STDINT_MIN(signed, bits, zero) \ - ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero)) - -#define _STDINT_MAX(signed, bits, zero) \ - ((signed) \ - ? ~ _STDINT_MIN (signed, bits, zero) \ - : ((((zero) + 1) << ((bits) ? (bits) - 1 : 0)) - 1) * 2 + 1) - -/* 7.18.1.1. Exact-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. */ - -#undef int8_t -#undef uint8_t -#define int8_t signed char -#define uint8_t unsigned char - -#undef int16_t -#undef uint16_t -#define int16_t short int -#define uint16_t unsigned short int - -#undef int32_t -#undef uint32_t -#define int32_t int -#define uint32_t unsigned int - -#undef int64_t -#if LONG_MAX >> 31 >> 31 == 1 -# define int64_t long int -#elif defined _MSC_VER -# define int64_t __int64 -#elif @HAVE_LONG_LONG_INT@ -# define int64_t long long int -#endif - -#undef uint64_t -#if ULONG_MAX >> 31 >> 31 >> 1 == 1 -# define uint64_t unsigned long int -#elif defined _MSC_VER -# define uint64_t unsigned __int64 -#elif @HAVE_UNSIGNED_LONG_LONG_INT@ -# define uint64_t unsigned long long int -#endif - -/* Avoid collision with Solaris 2.5.1 etc. */ -#define _UINT8_T -#define _UINT32_T -#define _UINT64_T - - -/* 7.18.1.2. Minimum-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types - are the same as the corresponding N_t types. */ - -#undef int_least8_t -#undef uint_least8_t -#undef int_least16_t -#undef uint_least16_t -#undef int_least32_t -#undef uint_least32_t -#undef int_least64_t -#undef uint_least64_t -#define int_least8_t int8_t -#define uint_least8_t uint8_t -#define int_least16_t int16_t -#define uint_least16_t uint16_t -#define int_least32_t int32_t -#define uint_least32_t uint32_t -#ifdef int64_t -# define int_least64_t int64_t -#endif -#ifdef uint64_t -# define uint_least64_t uint64_t -#endif - -/* 7.18.1.3. Fastest minimum-width integer types */ - -/* Note: Other substitutes may define these types differently. - It is not recommended to use these types in public header files. */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types - are taken from the same list of types. Assume that 'long int' - is fast enough for all narrower integers. */ - -#undef int_fast8_t -#undef uint_fast8_t -#undef int_fast16_t -#undef uint_fast16_t -#undef int_fast32_t -#undef uint_fast32_t -#undef int_fast64_t -#undef uint_fast64_t -#define int_fast8_t long int -#define uint_fast8_t unsigned int_fast8_t -#define int_fast16_t long int -#define uint_fast16_t unsigned int_fast16_t -#define int_fast32_t long int -#define uint_fast32_t unsigned int_fast32_t -#ifdef int64_t -# define int_fast64_t int64_t -#endif -#ifdef uint64_t -# define uint_fast64_t uint64_t -#endif - -/* 7.18.1.4. Integer types capable of holding object pointers */ - -#undef intptr_t -#undef uintptr_t -#define intptr_t long int -#define uintptr_t unsigned long int - -/* 7.18.1.5. Greatest-width integer types */ - -/* Note: These types are compiler dependent. It may be unwise to use them in - public header files. */ - -#undef intmax_t -#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 -# define intmax_t long long int -#elif defined int64_t -# define intmax_t int64_t -#else -# define intmax_t long int -#endif - -#undef uintmax_t -#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 -# define uintmax_t unsigned long long int -#elif defined uint64_t -# define uintmax_t uint64_t -#else -# define uintmax_t unsigned long int -#endif - -/* 7.18.2. Limits of specified-width integer types */ - -#if ! defined __cplusplus || defined __STDC_LIMIT_MACROS - -/* 7.18.2.1. Limits of exact-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. */ - -#undef INT8_MIN -#undef INT8_MAX -#undef UINT8_MAX -#define INT8_MIN (~ INT8_MAX) -#define INT8_MAX 127 -#define UINT8_MAX 255 - -#undef INT16_MIN -#undef INT16_MAX -#undef UINT16_MAX -#define INT16_MIN (~ INT16_MAX) -#define INT16_MAX 32767 -#define UINT16_MAX 65535 - -#undef INT32_MIN -#undef INT32_MAX -#undef UINT32_MAX -#define INT32_MIN (~ INT32_MAX) -#define INT32_MAX 2147483647 -#define UINT32_MAX 4294967295U - -#undef INT64_MIN -#undef INT64_MAX -#ifdef int64_t -# define INT64_MIN (~ INT64_MAX) -# define INT64_MAX INTMAX_C (9223372036854775807) -#endif - -#undef UINT64_MAX -#ifdef uint64_t -# define UINT64_MAX UINTMAX_C (18446744073709551615) -#endif - -/* 7.18.2.2. Limits of minimum-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types - are the same as the corresponding N_t types. */ - -#undef INT_LEAST8_MIN -#undef INT_LEAST8_MAX -#undef UINT_LEAST8_MAX -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#undef INT_LEAST16_MIN -#undef INT_LEAST16_MAX -#undef UINT_LEAST16_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#undef INT_LEAST32_MIN -#undef INT_LEAST32_MAX -#undef UINT_LEAST32_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#undef INT_LEAST64_MIN -#undef INT_LEAST64_MAX -#ifdef int64_t -# define INT_LEAST64_MIN INT64_MIN -# define INT_LEAST64_MAX INT64_MAX -#endif - -#undef UINT_LEAST64_MAX -#ifdef uint64_t -# define UINT_LEAST64_MAX UINT64_MAX -#endif - -/* 7.18.2.3. Limits of fastest minimum-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types - are taken from the same list of types. */ - -#undef INT_FAST8_MIN -#undef INT_FAST8_MAX -#undef UINT_FAST8_MAX -#define INT_FAST8_MIN LONG_MIN -#define INT_FAST8_MAX LONG_MAX -#define UINT_FAST8_MAX ULONG_MAX - -#undef INT_FAST16_MIN -#undef INT_FAST16_MAX -#undef UINT_FAST16_MAX -#define INT_FAST16_MIN LONG_MIN -#define INT_FAST16_MAX LONG_MAX -#define UINT_FAST16_MAX ULONG_MAX - -#undef INT_FAST32_MIN -#undef INT_FAST32_MAX -#undef UINT_FAST32_MAX -#define INT_FAST32_MIN LONG_MIN -#define INT_FAST32_MAX LONG_MAX -#define UINT_FAST32_MAX ULONG_MAX - -#undef INT_FAST64_MIN -#undef INT_FAST64_MAX -#ifdef int64_t -# define INT_FAST64_MIN INT64_MIN -# define INT_FAST64_MAX INT64_MAX -#endif - -#undef UINT_FAST64_MAX -#ifdef uint64_t -# define UINT_FAST64_MAX UINT64_MAX -#endif - -/* 7.18.2.4. Limits of integer types capable of holding object pointers */ - -#undef INTPTR_MIN -#undef INTPTR_MAX -#undef UINTPTR_MAX -#define INTPTR_MIN LONG_MIN -#define INTPTR_MAX LONG_MAX -#define UINTPTR_MAX ULONG_MAX - -/* 7.18.2.5. Limits of greatest-width integer types */ - -#undef INTMAX_MIN -#undef INTMAX_MAX -#define INTMAX_MIN (~ INTMAX_MAX) -#ifdef INT64_MAX -# define INTMAX_MAX INT64_MAX -#else -# define INTMAX_MAX INT32_MAX -#endif - -#undef UINTMAX_MAX -#ifdef UINT64_MAX -# define UINTMAX_MAX UINT64_MAX -#else -# define UINTMAX_MAX UINT32_MAX -#endif - -/* 7.18.3. Limits of other integer types */ - -/* ptrdiff_t limits */ -#undef PTRDIFF_MIN -#undef PTRDIFF_MAX -#define PTRDIFF_MIN \ - _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) -#define PTRDIFF_MAX \ - _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) - -/* sig_atomic_t limits */ -#undef SIG_ATOMIC_MIN -#undef SIG_ATOMIC_MAX -#define SIG_ATOMIC_MIN \ - _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ - 0@SIG_ATOMIC_T_SUFFIX@) -#define SIG_ATOMIC_MAX \ - _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ - 0@SIG_ATOMIC_T_SUFFIX@) - - -/* size_t limit */ -#undef SIZE_MAX -#define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) - -/* wchar_t limits */ -#undef WCHAR_MIN -#undef WCHAR_MAX -#define WCHAR_MIN \ - _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) -#define WCHAR_MAX \ - _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) - -/* wint_t limits */ -#undef WINT_MIN -#undef WINT_MAX -#define WINT_MIN \ - _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) -#define WINT_MAX \ - _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) - -#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */ - -/* 7.18.4. Macros for integer constants */ - -#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS - -/* 7.18.4.1. Macros for minimum-width integer constants */ -/* According to ISO C 99 Technical Corrigendum 1 */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ - -#undef INT8_C -#undef UINT8_C -#define INT8_C(x) x -#define UINT8_C(x) x - -#undef INT16_C -#undef UINT16_C -#define INT16_C(x) x -#define UINT16_C(x) x - -#undef INT32_C -#undef UINT32_C -#define INT32_C(x) x -#define UINT32_C(x) x ## U - -#undef INT64_C -#undef UINT64_C -#if LONG_MAX >> 31 >> 31 == 1 -# define INT64_C(x) x##L -#elif defined _MSC_VER -# define INT64_C(x) x##i64 -#elif @HAVE_LONG_LONG_INT@ -# define INT64_C(x) x##LL -#endif -#if ULONG_MAX >> 31 >> 31 >> 1 == 1 -# define UINT64_C(x) x##UL -#elif defined _MSC_VER -# define UINT64_C(x) x##ui64 -#elif @HAVE_UNSIGNED_LONG_LONG_INT@ -# define UINT64_C(x) x##ULL -#endif - -/* 7.18.4.2. Macros for greatest-width integer constants */ - -#undef INTMAX_C -#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 -# define INTMAX_C(x) x##LL -#elif defined int64_t -# define INTMAX_C(x) INT64_C(x) -#else -# define INTMAX_C(x) x##L -#endif - -#undef UINTMAX_C -#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 -# define UINTMAX_C(x) x##ULL -#elif defined uint64_t -# define UINTMAX_C(x) UINT64_C(x) -#else -# define UINTMAX_C(x) x##UL -#endif - -#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */ - -#endif /* _GL_STDINT_H */ diff --git a/src/bin/m4/lib/stdio--.h b/src/bin/m4/lib/stdio--.h deleted file mode 100644 index 2385e626ff..0000000000 --- a/src/bin/m4/lib/stdio--.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Like stdio.h, but redefine some names to avoid glitches. - - Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include -#include "stdio-safer.h" - -#undef fopen -#define fopen fopen_safer - -#undef tmpfile -#define tmpfile tmpfile_safer diff --git a/src/bin/m4/lib/stdio-safer.h b/src/bin/m4/lib/stdio-safer.h deleted file mode 100644 index 8329a1a093..0000000000 --- a/src/bin/m4/lib/stdio-safer.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Invoke stdio functions, but avoid some glitches. - - Copyright (C) 2001, 2003, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include - -FILE *fopen_safer (char const *, char const *); -FILE *tmpfile_safer (void); diff --git a/src/bin/m4/lib/stdlib--.h b/src/bin/m4/lib/stdlib--.h deleted file mode 100644 index b43b3dae6d..0000000000 --- a/src/bin/m4/lib/stdlib--.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Like stdlib.h, but redefine some names to avoid glitches. - - Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include -#include "stdlib-safer.h" - -#include "mkstemp.h" -#undef mkstemp -#define mkstemp mkstemp_safer diff --git a/src/bin/m4/lib/stdlib-safer.h b/src/bin/m4/lib/stdlib-safer.h deleted file mode 100644 index 8b1a7e11e5..0000000000 --- a/src/bin/m4/lib/stdlib-safer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Invoke stdlib.h functions, but avoid some glitches. - - Copyright (C) 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -int mkstemp_safer (char *); diff --git a/src/bin/m4/lib/strcase.h b/src/bin/m4/lib/strcase.h deleted file mode 100644 index 07d4c9a42b..0000000000 --- a/src/bin/m4/lib/strcase.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Case-insensitive string comparison functions. - Copyright (C) 1995-1996, 2001, 2003, 2005-2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _STRCASE_H -#define _STRCASE_H - -#include -/* Include header files with a possibly conflicting declarations of strcasecmp - before we define it as a macro, so that they will be no-ops if included - after strcasecmp is defined as a macro. */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* No known system has a strcasecmp() function that works correctly in - multibyte locales. Therefore we use our version always. */ -#define strcasecmp rpl_strcasecmp -/* Compare strings S1 and S2, ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less than, equal to or greater - than S2. - Note: This function may, in multibyte locales, return 0 for strings of - different lengths! */ -extern int strcasecmp (const char *s1, const char *s2); - -/* Compare no more than N characters of strings S1 and S2, ignoring case, - returning less than, equal to or greater than zero if S1 is - lexicographically less than, equal to or greater than S2. - Note: This function can not work correctly in multibyte locales. */ -#if ! HAVE_DECL_STRNCASECMP -extern int strncasecmp (const char *s1, const char *s2, size_t n); -#endif - - -#ifdef __cplusplus -} -#endif - - -#endif /* _STRCASE_H */ diff --git a/src/bin/m4/lib/strcasecmp.c b/src/bin/m4/lib/strcasecmp.c deleted file mode 100644 index 99d5dd22a3..0000000000 --- a/src/bin/m4/lib/strcasecmp.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Case-insensitive string comparison function. - Copyright (C) 1998-1999, 2005-2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2005, - based on earlier glibc code. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "strcase.h" - -#include -#include - -#if HAVE_MBRTOWC -# include "mbuiter.h" -#endif - -#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) - -/* Compare strings S1 and S2, ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less than, equal to or greater - than S2. - Note: This function may, in multibyte locales, return 0 for strings of - different lengths! */ -int -strcasecmp (const char *s1, const char *s2) -{ - if (s1 == s2) - return 0; - - /* Be careful not to look at the entire extent of s1 or s2 until needed. - This is useful because when two strings differ, the difference is - most often already in the very few first characters. */ -#if HAVE_MBRTOWC - if (MB_CUR_MAX > 1) - { - mbui_iterator_t iter1; - mbui_iterator_t iter2; - - mbui_init (iter1, s1); - mbui_init (iter2, s2); - - while (mbui_avail (iter1) && mbui_avail (iter2)) - { - int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2)); - - if (cmp != 0) - return cmp; - - mbui_advance (iter1); - mbui_advance (iter2); - } - if (mbui_avail (iter1)) - /* s2 terminated before s1. */ - return 1; - if (mbui_avail (iter2)) - /* s1 terminated before s2. */ - return -1; - return 0; - } - else -#endif - { - const unsigned char *p1 = (const unsigned char *) s1; - const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - do - { - c1 = TOLOWER (*p1); - c2 = TOLOWER (*p2); - - if (c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - if (UCHAR_MAX <= INT_MAX) - return c1 - c2; - else - /* On machines where 'char' and 'int' are types of the same size, the - difference of two 'unsigned char' values - including the sign bit - - doesn't fit in an 'int'. */ - return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); - } -} diff --git a/src/bin/m4/lib/strncasecmp.c b/src/bin/m4/lib/strncasecmp.c deleted file mode 100644 index f59b953a7d..0000000000 --- a/src/bin/m4/lib/strncasecmp.c +++ /dev/null @@ -1,63 +0,0 @@ -/* strncasecmp.c -- case insensitive string comparator - Copyright (C) 1998-1999, 2005-2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "strcase.h" - -#include -#include - -#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) - -/* Compare no more than N bytes of strings S1 and S2, - ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less - than, equal to or greater than S2. */ - -int -strncasecmp (const char *s1, const char *s2, size_t n) -{ - register const unsigned char *p1 = (const unsigned char *) s1; - register const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - if (p1 == p2 || n == 0) - return 0; - - do - { - c1 = TOLOWER (*p1); - c2 = TOLOWER (*p2); - - if (--n == 0 || c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - if (UCHAR_MAX <= INT_MAX) - return c1 - c2; - else - /* On machines where 'char' and 'int' are types of the same size, the - difference of two 'unsigned char' values - including the sign bit - - doesn't fit in an 'int'. */ - return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); -} diff --git a/src/bin/m4/lib/strnlen1.c b/src/bin/m4/lib/strnlen1.c deleted file mode 100644 index 422ed9e80c..0000000000 --- a/src/bin/m4/lib/strnlen1.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005-2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "strnlen1.h" - -#include - -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - If no '\0' terminator is found in that many characters, return MAXLEN. */ -/* This is the same as strnlen (string, maxlen - 1) + 1. */ -size_t -strnlen1 (const char *string, size_t maxlen) -{ - const char *end = (const char *) memchr (string, '\0', maxlen); - if (end != NULL) - return end - string + 1; - else - return maxlen; -} diff --git a/src/bin/m4/lib/strnlen1.h b/src/bin/m4/lib/strnlen1.h deleted file mode 100644 index 7ce7d0c803..0000000000 --- a/src/bin/m4/lib/strnlen1.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _STRNLEN1_H -#define _STRNLEN1_H - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - If no '\0' terminator is found in that many characters, return MAXLEN. */ -/* This is the same as strnlen (string, maxlen - 1) + 1. */ -extern size_t strnlen1 (const char *string, size_t maxlen); - - -#ifdef __cplusplus -} -#endif - - -#endif /* _STRNLEN1_H */ diff --git a/src/bin/m4/lib/strstr.c b/src/bin/m4/lib/strstr.c deleted file mode 100644 index f1e2ef6988..0000000000 --- a/src/bin/m4/lib/strstr.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Searching in a string. - Copyright (C) 2005-2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2005. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "strstr.h" - -#include /* for NULL */ - -#if HAVE_MBRTOWC -# include "mbuiter.h" -#endif - -/* Find the first occurrence of NEEDLE in HAYSTACK. */ -char * -strstr (const char *haystack, const char *needle) -{ - /* Be careful not to look at the entire extent of haystack or needle - until needed. This is useful because of these two cases: - - haystack may be very long, and a match of needle found early, - - needle may be very long, and not even a short initial segment of - needle may be found in haystack. */ -#if HAVE_MBRTOWC - if (MB_CUR_MAX > 1) - { - mbui_iterator_t iter_needle; - - mbui_init (iter_needle, needle); - if (mbui_avail (iter_needle)) - { - mbui_iterator_t iter_haystack; - - mbui_init (iter_haystack, haystack); - for (;; mbui_advance (iter_haystack)) - { - if (!mbui_avail (iter_haystack)) - /* No match. */ - return NULL; - - if (mb_equal (mbui_cur (iter_haystack), mbui_cur (iter_needle))) - /* The first character matches. */ - { - mbui_iterator_t rhaystack; - mbui_iterator_t rneedle; - - memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t)); - mbui_advance (rhaystack); - - mbui_init (rneedle, needle); - if (!mbui_avail (rneedle)) - abort (); - mbui_advance (rneedle); - - for (;; mbui_advance (rhaystack), mbui_advance (rneedle)) - { - if (!mbui_avail (rneedle)) - /* Found a match. */ - return (char *) mbui_cur_ptr (iter_haystack); - if (!mbui_avail (rhaystack)) - /* No match. */ - return NULL; - if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle))) - /* Nothing in this round. */ - break; - } - } - } - } - else - return (char *) haystack; - } - else -#endif - { - if (*needle != '\0') - { - /* Speed up the following searches of needle by caching its first - character. */ - char b = *needle++; - - for (;; haystack++) - { - if (*haystack == '\0') - /* No match. */ - return NULL; - if (*haystack == b) - /* The first character matches. */ - { - const char *rhaystack = haystack + 1; - const char *rneedle = needle; - - for (;; rhaystack++, rneedle++) - { - if (*rneedle == '\0') - /* Found a match. */ - return (char *) haystack; - if (*rhaystack == '\0') - /* No match. */ - return NULL; - if (*rhaystack != *rneedle) - /* Nothing in this round. */ - break; - } - } - } - } - else - return (char *) haystack; - } -} diff --git a/src/bin/m4/lib/strstr.h b/src/bin/m4/lib/strstr.h deleted file mode 100644 index a28b1401ea..0000000000 --- a/src/bin/m4/lib/strstr.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Searching in a string. - Copyright (C) 2001-2003, 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - - -/* Include string.h: on glibc systems, it contains a macro definition of - strstr() that would collide with our definition if included afterwards. */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* No known system has a strstr() function that works correctly in - multibyte locales. Therefore we use our version always. */ -#undef strstr -#define strstr rpl_strstr - -/* Find the first occurrence of NEEDLE in HAYSTACK. */ -extern char *strstr (const char *haystack, const char *needle); - -#ifdef __cplusplus -} -#endif diff --git a/src/bin/m4/lib/strtol.c b/src/bin/m4/lib/strtol.c deleted file mode 100644 index e409d28727..0000000000 --- a/src/bin/m4/lib/strtol.c +++ /dev/null @@ -1,437 +0,0 @@ -/* Convert string representation of a number into an integer value. - - Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005, 2006 - Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@gnu.org. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifdef _LIBC -# define USE_NUMBER_GROUPING -#else -# include -#endif - -#include -#include -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif - -#include -#include -#include -#include - -#ifdef USE_NUMBER_GROUPING -# include "../locale/localeinfo.h" -#endif - -/* Nonzero if we are defining `strtoul' or `strtoull', operating on - unsigned integers. */ -#ifndef UNSIGNED -# define UNSIGNED 0 -# define INT LONG int -#else -# define INT unsigned LONG int -#endif - -/* Determine the name. */ -#ifdef USE_IN_EXTENDED_LOCALE_MODEL -# if UNSIGNED -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol __wcstoull_l -# else -# define strtol __wcstoul_l -# endif -# else -# ifdef QUAD -# define strtol __strtoull_l -# else -# define strtol __strtoul_l -# endif -# endif -# else -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol __wcstoll_l -# else -# define strtol __wcstol_l -# endif -# else -# ifdef QUAD -# define strtol __strtoll_l -# else -# define strtol __strtol_l -# endif -# endif -# endif -#else -# if UNSIGNED -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol wcstoull -# else -# define strtol wcstoul -# endif -# else -# ifdef QUAD -# define strtol strtoull -# else -# define strtol strtoul -# endif -# endif -# else -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol wcstoll -# else -# define strtol wcstol -# endif -# else -# ifdef QUAD -# define strtol strtoll -# endif -# endif -# endif -#endif - -/* If QUAD is defined, we are defining `strtoll' or `strtoull', - operating on `long long int's. */ -#ifdef QUAD -# define LONG long long -# define STRTOL_LONG_MIN LONG_LONG_MIN -# define STRTOL_LONG_MAX LONG_LONG_MAX -# define STRTOL_ULONG_MAX ULONG_LONG_MAX - -/* The extra casts in the following macros work around compiler bugs, - e.g., in Cray C 5.0.3.0. */ - -/* True if negative values of the signed integer type T use two's - complement, ones' complement, or signed magnitude representation, - respectively. Much GNU code assumes two's complement, but some - people like to be portable to all possible C hosts. */ -# define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) -# define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) -# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) - -/* True if the arithmetic type T is signed. */ -# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) - -/* The maximum and minimum values for the integer type T. These - macros have undefined behavior if T is signed and has padding bits. - If this is a problem for you, please let us know how to fix it for - your host. */ -# define TYPE_MINIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) 0 \ - : TYPE_SIGNED_MAGNITUDE (t) \ - ? ~ (t) 0 \ - : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) -# define TYPE_MAXIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) -1 \ - : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) - -# ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long) -# endif -# ifndef LONG_LONG_MAX -# define LONG_LONG_MAX TYPE_MAXIMUM (long long int) -# endif -# ifndef LONG_LONG_MIN -# define LONG_LONG_MIN TYPE_MINIMUM (long long int) -# endif - -# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 - /* Work around gcc bug with using this constant. */ - static const unsigned long long int maxquad = ULONG_LONG_MAX; -# undef STRTOL_ULONG_MAX -# define STRTOL_ULONG_MAX maxquad -# endif -#else -# define LONG long -# define STRTOL_LONG_MIN LONG_MIN -# define STRTOL_LONG_MAX LONG_MAX -# define STRTOL_ULONG_MAX ULONG_MAX -#endif - - -/* We use this code also for the extended locale handling where the - function gets as an additional argument the locale which has to be - used. To access the values we have to redefine the _NL_CURRENT - macro. */ -#ifdef USE_IN_EXTENDED_LOCALE_MODEL -# undef _NL_CURRENT -# define _NL_CURRENT(category, item) \ - (current->values[_NL_ITEM_INDEX (item)].string) -# define LOCALE_PARAM , loc -# define LOCALE_PARAM_PROTO , __locale_t loc -#else -# define LOCALE_PARAM -# define LOCALE_PARAM_PROTO -#endif - -#if defined _LIBC || defined HAVE_WCHAR_H -# include -#endif - -#ifdef USE_WIDE_CHAR -# include -# define L_(Ch) L##Ch -# define UCHAR_TYPE wint_t -# define STRING_TYPE wchar_t -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __iswspace_l ((Ch), loc) -# define ISALPHA(Ch) __iswalpha_l ((Ch), loc) -# define TOUPPER(Ch) __towupper_l ((Ch), loc) -# else -# define ISSPACE(Ch) iswspace (Ch) -# define ISALPHA(Ch) iswalpha (Ch) -# define TOUPPER(Ch) towupper (Ch) -# endif -#else -# define L_(Ch) Ch -# define UCHAR_TYPE unsigned char -# define STRING_TYPE char -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __isspace_l ((Ch), loc) -# define ISALPHA(Ch) __isalpha_l ((Ch), loc) -# define TOUPPER(Ch) __toupper_l ((Ch), loc) -# else -# define ISSPACE(Ch) isspace (Ch) -# define ISALPHA(Ch) isalpha (Ch) -# define TOUPPER(Ch) toupper (Ch) -# endif -#endif - -#define INTERNAL(X) INTERNAL1(X) -#define INTERNAL1(X) __##X##_internal -#define WEAKNAME(X) WEAKNAME1(X) - -#ifdef USE_NUMBER_GROUPING -/* This file defines a function to check for correct grouping. */ -# include "grouping.h" -#endif - - - -/* Convert NPTR to an `unsigned long int' or `long int' in base BASE. - If BASE is 0 the base is determined by the presence of a leading - zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. - If BASE is < 2 or > 36, it is reset to 10. - If ENDPTR is not NULL, a pointer to the character after the last - one converted is stored in *ENDPTR. */ - -INT -INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, - int base, int group LOCALE_PARAM_PROTO) -{ - int negative; - register unsigned LONG int cutoff; - register unsigned int cutlim; - register unsigned LONG int i; - register const STRING_TYPE *s; - register UCHAR_TYPE c; - const STRING_TYPE *save, *end; - int overflow; - -#ifdef USE_NUMBER_GROUPING -# ifdef USE_IN_EXTENDED_LOCALE_MODEL - struct locale_data *current = loc->__locales[LC_NUMERIC]; -# endif - /* The thousands character of the current locale. */ - wchar_t thousands = L'\0'; - /* The numeric grouping specification of the current locale, - in the format described in . */ - const char *grouping; - - if (group) - { - grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); - if (*grouping <= 0 || *grouping == CHAR_MAX) - grouping = NULL; - else - { - /* Figure out the thousands separator character. */ -# if defined _LIBC || defined _HAVE_BTOWC - thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); - if (thousands == WEOF) - thousands = L'\0'; -# endif - if (thousands == L'\0') - grouping = NULL; - } - } - else - grouping = NULL; -#endif - - if (base < 0 || base == 1 || base > 36) - { - __set_errno (EINVAL); - return 0; - } - - save = s = nptr; - - /* Skip white space. */ - while (ISSPACE (*s)) - ++s; - if (*s == L_('\0')) - goto noconv; - - /* Check for a sign. */ - if (*s == L_('-')) - { - negative = 1; - ++s; - } - else if (*s == L_('+')) - { - negative = 0; - ++s; - } - else - negative = 0; - - /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ - if (*s == L_('0')) - { - if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) - { - s += 2; - base = 16; - } - else if (base == 0) - base = 8; - } - else if (base == 0) - base = 10; - - /* Save the pointer so we can check later if anything happened. */ - save = s; - -#ifdef USE_NUMBER_GROUPING - if (group) - { - /* Find the end of the digit string and check its grouping. */ - end = s; - for (c = *end; c != L_('\0'); c = *++end) - if ((wchar_t) c != thousands - && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) - && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) - break; - if (*s == thousands) - end = s; - else - end = correctly_grouped_prefix (s, end, thousands, grouping); - } - else -#endif - end = NULL; - - cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; - cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; - - overflow = 0; - i = 0; - for (c = *s; c != L_('\0'); c = *++s) - { - if (s == end) - break; - if (c >= L_('0') && c <= L_('9')) - c -= L_('0'); - else if (ISALPHA (c)) - c = TOUPPER (c) - L_('A') + 10; - else - break; - if ((int) c >= base) - break; - /* Check for overflow. */ - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; - else - { - i *= (unsigned LONG int) base; - i += c; - } - } - - /* Check if anything actually happened. */ - if (s == save) - goto noconv; - - /* Store in ENDPTR the address of one character - past the last character we converted. */ - if (endptr != NULL) - *endptr = (STRING_TYPE *) s; - -#if !UNSIGNED - /* Check for a value that is within the range of - `unsigned LONG int', but outside the range of `LONG int'. */ - if (overflow == 0 - && i > (negative - ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 - : (unsigned LONG int) STRTOL_LONG_MAX)) - overflow = 1; -#endif - - if (overflow) - { - __set_errno (ERANGE); -#if UNSIGNED - return STRTOL_ULONG_MAX; -#else - return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; -#endif - } - - /* Return the result of the appropriate sign. */ - return negative ? -i : i; - -noconv: - /* We must handle a special case here: the base is 0 or 16 and the - first two characters are '0' and 'x', but the rest are no - hexadecimal digits. This is no error case. We return 0 and - ENDPTR points to the `x`. */ - if (endptr != NULL) - { - if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') - && save[-2] == L_('0')) - *endptr = (STRING_TYPE *) &save[-1]; - else - /* There was no number to convert. */ - *endptr = (STRING_TYPE *) nptr; - } - - return 0L; -} - -/* External user entry point. */ - - -INT -#ifdef weak_function -weak_function -#endif -strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, - int base LOCALE_PARAM_PROTO) -{ - return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); -} diff --git a/src/bin/m4/lib/tempname.c b/src/bin/m4/lib/tempname.c deleted file mode 100644 index 919badb3dc..0000000000 --- a/src/bin/m4/lib/tempname.c +++ /dev/null @@ -1,322 +0,0 @@ -/* tempname.c - generate the name of a temporary file. - - Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */ - -#if !_LIBC -# include -# include "tempname.h" -#endif - -#include -#include - -#include -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif - -#include -#ifndef P_tmpdir -# define P_tmpdir "/tmp" -#endif -#ifndef TMP_MAX -# define TMP_MAX 238328 -#endif -#ifndef __GT_FILE -# define __GT_FILE 0 -# define __GT_BIGFILE 1 -# define __GT_DIR 2 -# define __GT_NOCREATE 3 -#endif - -#include -#include -#include - -#include - -#if HAVE_SYS_TIME_H || _LIBC -# include -#endif - -#include -#include - -#include - -#if _LIBC -# define struct_stat64 struct stat64 -# define small_open __open -# define large_open __open64 -#else -# define struct_stat64 struct stat -# define small_open open -# define large_open open -# define __gen_tempname gen_tempname -# define __getpid getpid -# define __gettimeofday gettimeofday -# define __mkdir mkdir -# define __lxstat64(version, file, buf) lstat (file, buf) -# define __xstat64(version, file, buf) stat (file, buf) -#endif - -#if ! (HAVE___SECURE_GETENV || _LIBC) -# define __secure_getenv getenv -#endif - -#ifdef _LIBC -# include -# if HP_TIMING_AVAIL -# define RANDOM_BITS(Var) \ - if (__builtin_expect (value == UINT64_C (0), 0)) \ - { \ - /* If this is the first time this function is used initialize \ - the variable we accumulate the value in to some somewhat \ - random value. If we'd not do this programs at startup time \ - might have a reduced set of possible names, at least on slow \ - machines. */ \ - struct timeval tv; \ - __gettimeofday (&tv, NULL); \ - value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ - } \ - HP_TIMING_NOW (Var) -# endif -#endif - -/* Use the widest available unsigned type if uint64_t is not - available. The algorithm below extracts a number less than 62**6 - (approximately 2**35.725) from uint64_t, so ancient hosts where - uintmax_t is only 32 bits lose about 3.725 bits of randomness, - which is better than not having mkstemp at all. */ -#if !defined UINT64_MAX && !defined uint64_t -# define uint64_t uintmax_t -#endif - -#if _LIBC -/* Return nonzero if DIR is an existent directory. */ -static int -direxists (const char *dir) -{ - struct_stat64 buf; - return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); -} - -/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is - non-null and exists, uses it; otherwise uses the first of $TMPDIR, - P_tmpdir, /tmp that exists. Copies into TMPL a template suitable - for use with mk[s]temp. Will fail (-1) if DIR is non-null and - doesn't exist, none of the searched dirs exists, or there's not - enough space in TMPL. */ -int -__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) -{ - const char *d; - size_t dlen, plen; - - if (!pfx || !pfx[0]) - { - pfx = "file"; - plen = 4; - } - else - { - plen = strlen (pfx); - if (plen > 5) - plen = 5; - } - - if (try_tmpdir) - { - d = __secure_getenv ("TMPDIR"); - if (d != NULL && direxists (d)) - dir = d; - else if (dir != NULL && direxists (dir)) - /* nothing */ ; - else - dir = NULL; - } - if (dir == NULL) - { - if (direxists (P_tmpdir)) - dir = P_tmpdir; - else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) - dir = "/tmp"; - else - { - __set_errno (ENOENT); - return -1; - } - } - - dlen = strlen (dir); - while (dlen > 1 && dir[dlen - 1] == '/') - dlen--; /* remove trailing slashes */ - - /* check we have room for "${dir}/${pfx}XXXXXX\0" */ - if (tmpl_len < dlen + 1 + plen + 6 + 1) - { - __set_errno (EINVAL); - return -1; - } - - sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); - return 0; -} -#endif /* _LIBC */ - -/* These are the characters used in temporary file names. */ -static const char letters[] = -"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -/* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed - does not exist at the time of the call to __gen_tempname. TMPL is - overwritten with the result. - - KIND may be one of: - __GT_NOCREATE: simply verify that the name does not exist - at the time of the call. - __GT_FILE: create the file using open(O_CREAT|O_EXCL) - and return a read-write fd. The file is mode 0600. - __GT_BIGFILE: same as __GT_FILE but use open64(). - __GT_DIR: create a directory, which will be mode 0700. - - We use a clever algorithm to get hard-to-predict names. */ -int -__gen_tempname (char *tmpl, int kind) -{ - int len; - char *XXXXXX; - static uint64_t value; - uint64_t random_time_bits; - unsigned int count; - int fd = -1; - int save_errno = errno; - struct_stat64 st; - - /* A lower bound on the number of temporary files to attempt to - generate. The maximum total number of temporary file names that - can exist for a given template is 62**6. It should never be - necessary to try all these combinations. Instead if a reasonable - number of names is tried (we define reasonable as 62**3) fail to - give the system administrator the chance to remove the problems. */ -#define ATTEMPTS_MIN (62 * 62 * 62) - - /* The number of times to attempt to generate a temporary file. To - conform to POSIX, this must be no smaller than TMP_MAX. */ -#if ATTEMPTS_MIN < TMP_MAX - unsigned int attempts = TMP_MAX; -#else - unsigned int attempts = ATTEMPTS_MIN; -#endif - - len = strlen (tmpl); - if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) - { - __set_errno (EINVAL); - return -1; - } - - /* This is where the Xs start. */ - XXXXXX = &tmpl[len - 6]; - - /* Get some more or less random data. */ -#ifdef RANDOM_BITS - RANDOM_BITS (random_time_bits); -#else -# if HAVE_GETTIMEOFDAY || _LIBC - { - struct timeval tv; - __gettimeofday (&tv, NULL); - random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; - } -# else - random_time_bits = time (NULL); -# endif -#endif - value += random_time_bits ^ __getpid (); - - for (count = 0; count < attempts; value += 7777, ++count) - { - uint64_t v = value; - - /* Fill in the random bits. */ - XXXXXX[0] = letters[v % 62]; - v /= 62; - XXXXXX[1] = letters[v % 62]; - v /= 62; - XXXXXX[2] = letters[v % 62]; - v /= 62; - XXXXXX[3] = letters[v % 62]; - v /= 62; - XXXXXX[4] = letters[v % 62]; - v /= 62; - XXXXXX[5] = letters[v % 62]; - - switch (kind) - { - case __GT_FILE: - fd = small_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - break; - - case __GT_BIGFILE: - fd = large_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - break; - - case __GT_DIR: - fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); - break; - - case __GT_NOCREATE: - /* This case is backward from the other three. __gen_tempname - succeeds if __xstat fails because the name does not exist. - Note the continue to bypass the common logic at the bottom - of the loop. */ - if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) - { - if (errno == ENOENT) - { - __set_errno (save_errno); - return 0; - } - else - /* Give up now. */ - return -1; - } - continue; - - default: - assert (! "invalid KIND in __gen_tempname"); - } - - if (fd >= 0) - { - __set_errno (save_errno); - return fd; - } - else if (errno != EEXIST) - return -1; - } - - /* We got out of the loop because we ran out of combinations to try. */ - __set_errno (EEXIST); - return -1; -} diff --git a/src/bin/m4/lib/tempname.h b/src/bin/m4/lib/tempname.h deleted file mode 100644 index c51fa69424..0000000000 --- a/src/bin/m4/lib/tempname.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Create a temporary file or directory. - - Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* header written by Eric Blake */ - -/* In gnulib, always prefer large files. GT_FILE maps to - __GT_BIGFILE, not __GT_FILE, for a reason. */ -#define GT_FILE 1 -#define GT_DIR 2 -#define GT_NOCREATE 3 - -/* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed - does not exist at the time of the call to gen_tempname. TMPL is - overwritten with the result. - - KIND may be one of: - GT_NOCREATE: simply verify that the name does not exist - at the time of the call. - GT_FILE: create a large file using open(O_CREAT|O_EXCL) - and return a read-write fd. The file is mode 0600. - GT_DIR: create a directory, which will be mode 0700. - - We use a clever algorithm to get hard-to-predict names. */ -extern int gen_tempname (char *tmpl, int kind); diff --git a/src/bin/m4/lib/tmpdir.c b/src/bin/m4/lib/tmpdir.c deleted file mode 100644 index d29a005789..0000000000 --- a/src/bin/m4/lib/tmpdir.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (C) 1999, 2001-2002, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Extracted from sysdeps/posix/tempname.c. */ - -#include - -/* Specification. */ -#include "tmpdir.h" - -#include -#include -#include - -#include -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif - -#include -#ifndef P_tmpdir -# define P_tmpdir "/tmp" -#endif - -#include - -#if _LIBC -# define struct_stat64 struct stat64 -#else -# define struct_stat64 struct stat -# define __xstat64(version, path, buf) stat (path, buf) -#endif - -#if ! (HAVE___SECURE_GETENV || _LIBC) -# define __secure_getenv getenv -#endif - -/* Pathname support. - ISSLASH(C) tests whether C is a directory separator character. - */ -#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ - /* Win32, Cygwin, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -#else - /* Unix */ -# define ISSLASH(C) ((C) == '/') -#endif - - -/* Return nonzero if DIR is an existent directory. */ -static bool -direxists (const char *dir) -{ - struct_stat64 buf; - return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); -} - -/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is - non-null and exists, uses it; otherwise uses the first of $TMPDIR, - P_tmpdir, /tmp that exists. Copies into TMPL a template suitable - for use with mk[s]temp. Will fail (-1) if DIR is non-null and - doesn't exist, none of the searched dirs exists, or there's not - enough space in TMPL. */ -int -path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - bool try_tmpdir) -{ - const char *d; - size_t dlen, plen; - - if (!pfx || !pfx[0]) - { - pfx = "file"; - plen = 4; - } - else - { - plen = strlen (pfx); - if (plen > 5) - plen = 5; - } - - if (try_tmpdir) - { - d = __secure_getenv ("TMPDIR"); - if (d != NULL && direxists (d)) - dir = d; - else if (dir != NULL && direxists (dir)) - /* nothing */ ; - else - dir = NULL; - } - if (dir == NULL) - { - if (direxists (P_tmpdir)) - dir = P_tmpdir; - else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) - dir = "/tmp"; - else - { - __set_errno (ENOENT); - return -1; - } - } - - dlen = strlen (dir); - while (dlen >= 1 && ISSLASH (dir[dlen - 1])) - dlen--; /* remove trailing slashes */ - - /* check we have room for "${dir}/${pfx}XXXXXX\0" */ - if (tmpl_len < dlen + 1 + plen + 6 + 1) - { - __set_errno (EINVAL); - return -1; - } - - sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); - return 0; -} diff --git a/src/bin/m4/lib/tmpdir.h b/src/bin/m4/lib/tmpdir.h deleted file mode 100644 index 454e5cc184..0000000000 --- a/src/bin/m4/lib/tmpdir.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Determine a temporary directory. - Copyright (C) 2001-2002 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include -#include - -/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is - non-null and exists, uses it; otherwise uses the first of $TMPDIR, - P_tmpdir, /tmp that exists. Copies into TMPL a template suitable - for use with mk[s]temp. Will fail (-1) if DIR is non-null and - doesn't exist, none of the searched dirs exists, or there's not - enough space in TMPL. */ -extern int path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, bool try_tmpdir); diff --git a/src/bin/m4/lib/unistd--.h b/src/bin/m4/lib/unistd--.h deleted file mode 100644 index 1fe6ce8b27..0000000000 --- a/src/bin/m4/lib/unistd--.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Like unistd.h, but redefine some names to avoid glitches. - - Copyright (C) 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -#include -#include "unistd-safer.h" - -#undef dup -#define dup dup_safer - -#undef pipe -#define pipe pipe_safer diff --git a/src/bin/m4/lib/unistd-safer.h b/src/bin/m4/lib/unistd-safer.h deleted file mode 100644 index f95999d391..0000000000 --- a/src/bin/m4/lib/unistd-safer.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Invoke unistd-like functions, but avoid some glitches. - - Copyright (C) 2001, 2003, 2005 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert. */ - -int dup_safer (int); -int fd_safer (int); -int pipe_safer (int[2]); diff --git a/src/bin/m4/lib/unlocked-io.h b/src/bin/m4/lib/unlocked-io.h deleted file mode 100644 index d00930361c..0000000000 --- a/src/bin/m4/lib/unlocked-io.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Prefer faster, non-thread-safe stdio functions if available. - - Copyright (C) 2001, 2002, 2003, 2004 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#ifndef UNLOCKED_IO_H -# define UNLOCKED_IO_H 1 - -/* These are wrappers for functions/macros from the GNU C library, and - from other C libraries supporting POSIX's optional thread-safe functions. - - The standard I/O functions are thread-safe. These *_unlocked ones are - more efficient but not thread-safe. That they're not thread-safe is - fine since all of the applications in this package are single threaded. - - Also, some code that is shared with the GNU C library may invoke - the *_unlocked functions directly. On hosts that lack those - functions, invoke the non-thread-safe versions instead. */ - -# include - -# if HAVE_DECL_CLEARERR_UNLOCKED -# undef clearerr -# define clearerr(x) clearerr_unlocked (x) -# else -# define clearerr_unlocked(x) clearerr (x) -# endif - -# if HAVE_DECL_FEOF_UNLOCKED -# undef feof -# define feof(x) feof_unlocked (x) -# else -# define feof_unlocked(x) feof (x) -# endif - -# if HAVE_DECL_FERROR_UNLOCKED -# undef ferror -# define ferror(x) ferror_unlocked (x) -# else -# define ferror_unlocked(x) ferror (x) -# endif - -# if HAVE_DECL_FFLUSH_UNLOCKED -# undef fflush -# define fflush(x) fflush_unlocked (x) -# else -# define fflush_unlocked(x) fflush (x) -# endif - -# if HAVE_DECL_FGETS_UNLOCKED -# undef fgets -# define fgets(x,y,z) fgets_unlocked (x,y,z) -# else -# define fgets_unlocked(x,y,z) fgets (x,y,z) -# endif - -# if HAVE_DECL_FPUTC_UNLOCKED -# undef fputc -# define fputc(x,y) fputc_unlocked (x,y) -# else -# define fputc_unlocked(x,y) fputc (x,y) -# endif - -# if HAVE_DECL_FPUTS_UNLOCKED -# undef fputs -# define fputs(x,y) fputs_unlocked (x,y) -# else -# define fputs_unlocked(x,y) fputs (x,y) -# endif - -# if HAVE_DECL_FREAD_UNLOCKED -# undef fread -# define fread(w,x,y,z) fread_unlocked (w,x,y,z) -# else -# define fread_unlocked(w,x,y,z) fread (w,x,y,z) -# endif - -# if HAVE_DECL_FWRITE_UNLOCKED -# undef fwrite -# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) -# else -# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) -# endif - -# if HAVE_DECL_GETC_UNLOCKED -# undef getc -# define getc(x) getc_unlocked (x) -# else -# define getc_unlocked(x) getc (x) -# endif - -# if HAVE_DECL_GETCHAR_UNLOCKED -# undef getchar -# define getchar() getchar_unlocked () -# else -# define getchar_unlocked() getchar () -# endif - -# if HAVE_DECL_PUTC_UNLOCKED -# undef putc -# define putc(x,y) putc_unlocked (x,y) -# else -# define putc_unlocked(x,y) putc (x,y) -# endif - -# if HAVE_DECL_PUTCHAR_UNLOCKED -# undef putchar -# define putchar(x) putchar_unlocked (x) -# else -# define putchar_unlocked(x) putchar (x) -# endif - -# undef flockfile -# define flockfile(x) ((void) 0) - -# undef ftrylockfile -# define ftrylockfile(x) 0 - -# undef funlockfile -# define funlockfile(x) ((void) 0) - -#endif /* UNLOCKED_IO_H */ diff --git a/src/bin/m4/lib/vasnprintf.c b/src/bin/m4/lib/vasnprintf.c deleted file mode 100644 index 0fe2aada9f..0000000000 --- a/src/bin/m4/lib/vasnprintf.c +++ /dev/null @@ -1,889 +0,0 @@ -/* vsprintf with automatic memory allocation. - Copyright (C) 1999, 2002-2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Tell glibc's to provide a prototype for snprintf(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#include -#ifndef IN_LIBINTL -# include -#endif - -/* Specification. */ -#if WIDE_CHAR_VERSION -# include "vasnwprintf.h" -#else -# include "vasnprintf.h" -#endif - -#include /* snprintf(), sprintf() */ -#include /* abort(), malloc(), realloc(), free() */ -#include /* memcpy(), strlen() */ -#include /* errno */ -#include /* CHAR_BIT */ -#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ -#if WIDE_CHAR_VERSION -# include "wprintf-parse.h" -#else -# include "printf-parse.h" -#endif - -/* Checked size_t computations. */ -#include "xsize.h" - -#ifdef HAVE_WCHAR_T -# ifdef HAVE_WCSLEN -# define local_wcslen wcslen -# else - /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid - a dependency towards this library, here is a local substitute. - Define this substitute only once, even if this file is included - twice in the same compilation unit. */ -# ifndef local_wcslen_defined -# define local_wcslen_defined 1 -static size_t -local_wcslen (const wchar_t *s) -{ - const wchar_t *ptr; - - for (ptr = s; *ptr != (wchar_t) 0; ptr++) - ; - return ptr - s; -} -# endif -# endif -#endif - -#if WIDE_CHAR_VERSION -# define VASNPRINTF vasnwprintf -# define CHAR_T wchar_t -# define DIRECTIVE wchar_t_directive -# define DIRECTIVES wchar_t_directives -# define PRINTF_PARSE wprintf_parse -# define USE_SNPRINTF 1 -# if HAVE_DECL__SNWPRINTF - /* On Windows, the function swprintf() has a different signature than - on Unix; we use the _snwprintf() function instead. */ -# define SNPRINTF _snwprintf -# else - /* Unix. */ -# define SNPRINTF swprintf -# endif -#else -# define VASNPRINTF vasnprintf -# define CHAR_T char -# define DIRECTIVE char_directive -# define DIRECTIVES char_directives -# define PRINTF_PARSE printf_parse -# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) -# if HAVE_DECL__SNPRINTF - /* Windows. */ -# define SNPRINTF _snprintf -# else - /* Unix. */ -# define SNPRINTF snprintf -# endif -#endif - -CHAR_T * -VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) -{ - DIRECTIVES d; - arguments a; - - if (PRINTF_PARSE (format, &d, &a) < 0) - { - errno = EINVAL; - return NULL; - } - -#define CLEANUP() \ - free (d.dir); \ - if (a.arg) \ - free (a.arg); - - if (printf_fetchargs (args, &a) < 0) - { - CLEANUP (); - errno = EINVAL; - return NULL; - } - - { - size_t buf_neededlength; - CHAR_T *buf; - CHAR_T *buf_malloced; - const CHAR_T *cp; - size_t i; - DIRECTIVE *dp; - /* Output string accumulator. */ - CHAR_T *result; - size_t allocated; - size_t length; - - /* Allocate a small buffer that will hold a directive passed to - sprintf or snprintf. */ - buf_neededlength = - xsum4 (7, d.max_width_length, d.max_precision_length, 6); -#if HAVE_ALLOCA - if (buf_neededlength < 4000 / sizeof (CHAR_T)) - { - buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); - buf_malloced = NULL; - } - else -#endif - { - size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); - if (size_overflow_p (buf_memsize)) - goto out_of_memory_1; - buf = (CHAR_T *) malloc (buf_memsize); - if (buf == NULL) - goto out_of_memory_1; - buf_malloced = buf; - } - - if (resultbuf != NULL) - { - result = resultbuf; - allocated = *lengthp; - } - else - { - result = NULL; - allocated = 0; - } - length = 0; - /* Invariants: - result is either == resultbuf or == NULL or malloc-allocated. - If length > 0, then result != NULL. */ - - /* Ensures that allocated >= needed. Aborts through a jump to - out_of_memory if needed is SIZE_MAX or otherwise too big. */ -#define ENSURE_ALLOCATION(needed) \ - if ((needed) > allocated) \ - { \ - size_t memory_size; \ - CHAR_T *memory; \ - \ - allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ - if ((needed) > allocated) \ - allocated = (needed); \ - memory_size = xtimes (allocated, sizeof (CHAR_T)); \ - if (size_overflow_p (memory_size)) \ - goto out_of_memory; \ - if (result == resultbuf || result == NULL) \ - memory = (CHAR_T *) malloc (memory_size); \ - else \ - memory = (CHAR_T *) realloc (result, memory_size); \ - if (memory == NULL) \ - goto out_of_memory; \ - if (result == resultbuf && length > 0) \ - memcpy (memory, result, length * sizeof (CHAR_T)); \ - result = memory; \ - } - - for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) - { - if (cp != dp->dir_start) - { - size_t n = dp->dir_start - cp; - size_t augmented_length = xsum (length, n); - - ENSURE_ALLOCATION (augmented_length); - memcpy (result + length, cp, n * sizeof (CHAR_T)); - length = augmented_length; - } - if (i == d.count) - break; - - /* Execute a single directive. */ - if (dp->conversion == '%') - { - size_t augmented_length; - - if (!(dp->arg_index == ARG_NONE)) - abort (); - augmented_length = xsum (length, 1); - ENSURE_ALLOCATION (augmented_length); - result[length] = '%'; - length = augmented_length; - } - else - { - if (!(dp->arg_index != ARG_NONE)) - abort (); - - if (dp->conversion == 'n') - { - switch (a.arg[dp->arg_index].type) - { - case TYPE_COUNT_SCHAR_POINTER: - *a.arg[dp->arg_index].a.a_count_schar_pointer = length; - break; - case TYPE_COUNT_SHORT_POINTER: - *a.arg[dp->arg_index].a.a_count_short_pointer = length; - break; - case TYPE_COUNT_INT_POINTER: - *a.arg[dp->arg_index].a.a_count_int_pointer = length; - break; - case TYPE_COUNT_LONGINT_POINTER: - *a.arg[dp->arg_index].a.a_count_longint_pointer = length; - break; -#ifdef HAVE_LONG_LONG_INT - case TYPE_COUNT_LONGLONGINT_POINTER: - *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; - break; -#endif - default: - abort (); - } - } - else - { - arg_type type = a.arg[dp->arg_index].type; - CHAR_T *p; - unsigned int prefix_count; - int prefixes[2]; -#if !USE_SNPRINTF - size_t tmp_length; - CHAR_T tmpbuf[700]; - CHAR_T *tmp; - - /* Allocate a temporary buffer of sufficient size for calling - sprintf. */ - { - size_t width; - size_t precision; - - width = 0; - if (dp->width_start != dp->width_end) - { - if (dp->width_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->width_arg_index].a.a_int; - width = (arg < 0 ? (unsigned int) (-arg) : arg); - } - else - { - const CHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - } - - precision = 6; - if (dp->precision_start != dp->precision_end) - { - if (dp->precision_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->precision_arg_index].a.a_int; - precision = (arg < 0 ? 0 : arg); - } - else - { - const CHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - } - } - - switch (dp->conversion) - { - - case 'd': case 'i': case 'u': -# ifdef HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Multiply by 2, as an estimate for FLAG_GROUP. */ - tmp_length = xsum (tmp_length, tmp_length); - /* Add 1, to account for a leading sign. */ - tmp_length = xsum (tmp_length, 1); - break; - - case 'o': -# ifdef HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Add 1, to account for a leading sign. */ - tmp_length = xsum (tmp_length, 1); - break; - - case 'x': case 'X': -# ifdef HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Add 2, to account for a leading sign or alternate form. */ - tmp_length = xsum (tmp_length, 2); - break; - - case 'f': case 'F': -# ifdef HAVE_LONG_DOUBLE - if (type == TYPE_LONGDOUBLE) - tmp_length = - (unsigned int) (LDBL_MAX_EXP - * 0.30103 /* binary -> decimal */ - * 2 /* estimate for FLAG_GROUP */ - ) - + 1 /* turn floor into ceil */ - + 10; /* sign, decimal point etc. */ - else -# endif - tmp_length = - (unsigned int) (DBL_MAX_EXP - * 0.30103 /* binary -> decimal */ - * 2 /* estimate for FLAG_GROUP */ - ) - + 1 /* turn floor into ceil */ - + 10; /* sign, decimal point etc. */ - tmp_length = xsum (tmp_length, precision); - break; - - case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': - tmp_length = - 12; /* sign, decimal point, exponent etc. */ - tmp_length = xsum (tmp_length, precision); - break; - - case 'c': -# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION - if (type == TYPE_WIDE_CHAR) - tmp_length = MB_CUR_MAX; - else -# endif - tmp_length = 1; - break; - - case 's': -# ifdef HAVE_WCHAR_T - if (type == TYPE_WIDE_STRING) - { - tmp_length = - local_wcslen (a.arg[dp->arg_index].a.a_wide_string); - -# if !WIDE_CHAR_VERSION - tmp_length = xtimes (tmp_length, MB_CUR_MAX); -# endif - } - else -# endif - tmp_length = strlen (a.arg[dp->arg_index].a.a_string); - break; - - case 'p': - tmp_length = - (unsigned int) (sizeof (void *) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1 /* turn floor into ceil */ - + 2; /* account for leading 0x */ - break; - - default: - abort (); - } - - if (tmp_length < width) - tmp_length = width; - - tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - } - - if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) - tmp = tmpbuf; - else - { - size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); - - if (size_overflow_p (tmp_memsize)) - /* Overflow, would lead to out of memory. */ - goto out_of_memory; - tmp = (CHAR_T *) malloc (tmp_memsize); - if (tmp == NULL) - /* Out of memory. */ - goto out_of_memory; - } -#endif - - /* Construct the format string for calling snprintf or - sprintf. */ - p = buf; - *p++ = '%'; - if (dp->flags & FLAG_GROUP) - *p++ = '\''; - if (dp->flags & FLAG_LEFT) - *p++ = '-'; - if (dp->flags & FLAG_SHOWSIGN) - *p++ = '+'; - if (dp->flags & FLAG_SPACE) - *p++ = ' '; - if (dp->flags & FLAG_ALT) - *p++ = '#'; - if (dp->flags & FLAG_ZERO) - *p++ = '0'; - if (dp->width_start != dp->width_end) - { - size_t n = dp->width_end - dp->width_start; - memcpy (p, dp->width_start, n * sizeof (CHAR_T)); - p += n; - } - if (dp->precision_start != dp->precision_end) - { - size_t n = dp->precision_end - dp->precision_start; - memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); - p += n; - } - - switch (type) - { -#ifdef HAVE_LONG_LONG_INT - case TYPE_LONGLONGINT: - case TYPE_ULONGLONGINT: - *p++ = 'l'; - /*FALLTHROUGH*/ -#endif - case TYPE_LONGINT: - case TYPE_ULONGINT: -#ifdef HAVE_WINT_T - case TYPE_WIDE_CHAR: -#endif -#ifdef HAVE_WCHAR_T - case TYPE_WIDE_STRING: -#endif - *p++ = 'l'; - break; -#ifdef HAVE_LONG_DOUBLE - case TYPE_LONGDOUBLE: - *p++ = 'L'; - break; -#endif - default: - break; - } - *p = dp->conversion; -#if USE_SNPRINTF - p[1] = '%'; - p[2] = 'n'; - p[3] = '\0'; -#else - p[1] = '\0'; -#endif - - /* Construct the arguments for calling snprintf or sprintf. */ - prefix_count = 0; - if (dp->width_arg_index != ARG_NONE) - { - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; - } - if (dp->precision_arg_index != ARG_NONE) - { - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; - } - -#if USE_SNPRINTF - /* Prepare checking whether snprintf returns the count - via %n. */ - ENSURE_ALLOCATION (xsum (length, 1)); - result[length] = '\0'; -#endif - - for (;;) - { - size_t maxlen; - int count; - int retcount; - - maxlen = allocated - length; - count = -1; - retcount = 0; - -#if USE_SNPRINTF -# define SNPRINTF_BUF(arg) \ - switch (prefix_count) \ - { \ - case 0: \ - retcount = SNPRINTF (result + length, maxlen, buf, \ - arg, &count); \ - break; \ - case 1: \ - retcount = SNPRINTF (result + length, maxlen, buf, \ - prefixes[0], arg, &count); \ - break; \ - case 2: \ - retcount = SNPRINTF (result + length, maxlen, buf, \ - prefixes[0], prefixes[1], arg, \ - &count); \ - break; \ - default: \ - abort (); \ - } -#else -# define SNPRINTF_BUF(arg) \ - switch (prefix_count) \ - { \ - case 0: \ - count = sprintf (tmp, buf, arg); \ - break; \ - case 1: \ - count = sprintf (tmp, buf, prefixes[0], arg); \ - break; \ - case 2: \ - count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ - arg); \ - break; \ - default: \ - abort (); \ - } -#endif - - switch (type) - { - case TYPE_SCHAR: - { - int arg = a.arg[dp->arg_index].a.a_schar; - SNPRINTF_BUF (arg); - } - break; - case TYPE_UCHAR: - { - unsigned int arg = a.arg[dp->arg_index].a.a_uchar; - SNPRINTF_BUF (arg); - } - break; - case TYPE_SHORT: - { - int arg = a.arg[dp->arg_index].a.a_short; - SNPRINTF_BUF (arg); - } - break; - case TYPE_USHORT: - { - unsigned int arg = a.arg[dp->arg_index].a.a_ushort; - SNPRINTF_BUF (arg); - } - break; - case TYPE_INT: - { - int arg = a.arg[dp->arg_index].a.a_int; - SNPRINTF_BUF (arg); - } - break; - case TYPE_UINT: - { - unsigned int arg = a.arg[dp->arg_index].a.a_uint; - SNPRINTF_BUF (arg); - } - break; - case TYPE_LONGINT: - { - long int arg = a.arg[dp->arg_index].a.a_longint; - SNPRINTF_BUF (arg); - } - break; - case TYPE_ULONGINT: - { - unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; - SNPRINTF_BUF (arg); - } - break; -#ifdef HAVE_LONG_LONG_INT - case TYPE_LONGLONGINT: - { - long long int arg = a.arg[dp->arg_index].a.a_longlongint; - SNPRINTF_BUF (arg); - } - break; - case TYPE_ULONGLONGINT: - { - unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_DOUBLE: - { - double arg = a.arg[dp->arg_index].a.a_double; - SNPRINTF_BUF (arg); - } - break; -#ifdef HAVE_LONG_DOUBLE - case TYPE_LONGDOUBLE: - { - long double arg = a.arg[dp->arg_index].a.a_longdouble; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_CHAR: - { - int arg = a.arg[dp->arg_index].a.a_char; - SNPRINTF_BUF (arg); - } - break; -#ifdef HAVE_WINT_T - case TYPE_WIDE_CHAR: - { - wint_t arg = a.arg[dp->arg_index].a.a_wide_char; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_STRING: - { - const char *arg = a.arg[dp->arg_index].a.a_string; - SNPRINTF_BUF (arg); - } - break; -#ifdef HAVE_WCHAR_T - case TYPE_WIDE_STRING: - { - const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_POINTER: - { - void *arg = a.arg[dp->arg_index].a.a_pointer; - SNPRINTF_BUF (arg); - } - break; - default: - abort (); - } - -#if USE_SNPRINTF - /* Portability: Not all implementations of snprintf() - are ISO C 99 compliant. Determine the number of - bytes that snprintf() has produced or would have - produced. */ - if (count >= 0) - { - /* Verify that snprintf() has NUL-terminated its - result. */ - if (count < maxlen && result[length + count] != '\0') - abort (); - /* Portability hack. */ - if (retcount > count) - count = retcount; - } - else - { - /* snprintf() doesn't understand the '%n' - directive. */ - if (p[1] != '\0') - { - /* Don't use the '%n' directive; instead, look - at the snprintf() return value. */ - p[1] = '\0'; - continue; - } - else - { - /* Look at the snprintf() return value. */ - if (retcount < 0) - { - /* HP-UX 10.20 snprintf() is doubly deficient: - It doesn't understand the '%n' directive, - *and* it returns -1 (rather than the length - that would have been required) when the - buffer is too small. */ - size_t bigger_need = - xsum (xtimes (allocated, 2), 12); - ENSURE_ALLOCATION (bigger_need); - continue; - } - else - count = retcount; - } - } -#endif - - /* Attempt to handle failure. */ - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EINVAL; - return NULL; - } - -#if !USE_SNPRINTF - if (count >= tmp_length) - /* tmp_length was incorrectly calculated - fix the - code above! */ - abort (); -#endif - - /* Make room for the result. */ - if (count >= maxlen) - { - /* Need at least count bytes. But allocate - proportionally, to avoid looping eternally if - snprintf() reports a too small count. */ - size_t n = - xmax (xsum (length, count), xtimes (allocated, 2)); - - ENSURE_ALLOCATION (n); -#if USE_SNPRINTF - continue; -#endif - } - -#if USE_SNPRINTF - /* The snprintf() result did fit. */ -#else - /* Append the sprintf() result. */ - memcpy (result + length, tmp, count * sizeof (CHAR_T)); - if (tmp != tmpbuf) - free (tmp); -#endif - - length += count; - break; - } - } - } - } - - /* Add the final NUL. */ - ENSURE_ALLOCATION (xsum (length, 1)); - result[length] = '\0'; - - if (result != resultbuf && length + 1 < allocated) - { - /* Shrink the allocated memory if possible. */ - CHAR_T *memory; - - memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); - if (memory != NULL) - result = memory; - } - - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - *lengthp = length; - /* Note that we can produce a big string of a length > INT_MAX. POSIX - says that snprintf() fails with errno = EOVERFLOW in this case, but - that's only because snprintf() returns an 'int'. This function does - not have this limitation. */ - return result; - - out_of_memory: - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - out_of_memory_1: - CLEANUP (); - errno = ENOMEM; - return NULL; - } -} - -#undef SNPRINTF -#undef USE_SNPRINTF -#undef PRINTF_PARSE -#undef DIRECTIVES -#undef DIRECTIVE -#undef CHAR_T -#undef VASNPRINTF diff --git a/src/bin/m4/lib/vasnprintf.h b/src/bin/m4/lib/vasnprintf.h deleted file mode 100644 index 894008caec..0000000000 --- a/src/bin/m4/lib/vasnprintf.h +++ /dev/null @@ -1,77 +0,0 @@ -/* vsprintf with automatic memory allocation. - Copyright (C) 2002-2004 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _VASNPRINTF_H -#define _VASNPRINTF_H - -/* Get va_list. */ -#include - -/* Get size_t. */ -#include - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ -# define __attribute__(Spec) /* empty */ -# endif -/* The __-protected variants of `format' and `printf' attributes - are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __format__ format -# define __printf__ printf -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Write formatted output to a string dynamically allocated with malloc(). - You can pass a preallocated buffer for the result in RESULTBUF and its - size in *LENGTHP; otherwise you pass RESULTBUF = NULL. - If successful, return the address of the string (this may be = RESULTBUF - if no dynamic memory allocation was necessary) and set *LENGTHP to the - number of resulting bytes, excluding the trailing NUL. Upon error, set - errno and return NULL. - - When dynamic memory allocation occurs, the preallocated buffer is left - alone (with possibly modified contents). This makes it possible to use - a statically allocated or stack-allocated buffer, like this: - - char buf[100]; - size_t len = sizeof (buf); - char *output = vasnprintf (buf, &len, format, args); - if (output == NULL) - ... error handling ...; - else - { - ... use the output string ...; - if (output != buf) - free (output); - } - */ -extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 3, 0))); - -#ifdef __cplusplus -} -#endif - -#endif /* _VASNPRINTF_H */ diff --git a/src/bin/m4/lib/vasprintf.c b/src/bin/m4/lib/vasprintf.c deleted file mode 100644 index 824707345a..0000000000 --- a/src/bin/m4/lib/vasprintf.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 1999, 2002, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "vasprintf.h" - -#include -#include -#include - -#include "vasnprintf.h" - -/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ -#ifndef EOVERFLOW -# define EOVERFLOW E2BIG -#endif - -int -vasprintf (char **resultp, const char *format, va_list args) -{ - size_t length; - char *result = vasnprintf (NULL, &length, format, args); - if (result == NULL) - return -1; - - if (length > INT_MAX) - { - free (result); - errno = EOVERFLOW; - return -1; - } - - *resultp = result; - /* Return the number of resulting bytes, excluding the trailing NUL. */ - return length; -} diff --git a/src/bin/m4/lib/vasprintf.h b/src/bin/m4/lib/vasprintf.h deleted file mode 100644 index ab5515ce7f..0000000000 --- a/src/bin/m4/lib/vasprintf.h +++ /dev/null @@ -1,63 +0,0 @@ -/* vsprintf with automatic memory allocation. - Copyright (C) 2002-2003 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _VASPRINTF_H -#define _VASPRINTF_H - -#if HAVE_VASPRINTF - -/* Get asprintf(), vasprintf() declarations. */ -#include - -#else - -/* Get va_list. */ -#include - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ -# define __attribute__(Spec) /* empty */ -# endif -/* The __-protected variants of `format' and `printf' attributes - are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __format__ format -# define __printf__ printf -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Write formatted output to a string dynamically allocated with malloc(). - If the memory allocation succeeds, store the address of the string in - *RESULT and return the number of resulting bytes, excluding the trailing - NUL. Upon memory allocation error, or some other error, return -1. */ -extern int asprintf (char **result, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); -extern int vasprintf (char **result, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif /* _VASPRINTF_H */ diff --git a/src/bin/m4/lib/verify.h b/src/bin/m4/lib/verify.h deleted file mode 100644 index d603b17379..0000000000 --- a/src/bin/m4/lib/verify.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Compile-time assert-like macros. - - Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ - -#ifndef VERIFY_H -# define VERIFY_H 1 - -/* Each of these macros verifies that its argument R is nonzero. To - be portable, R should be an integer constant expression. Unlike - assert (R), there is no run-time overhead. - - There are two macros, since no single macro can be used in all - contexts in C. verify_true (R) is for scalar contexts, including - integer constant expression contexts. verify (R) is for declaration - contexts, e.g., the top level. - - Symbols ending in "__" are private to this header. - - The code below uses several ideas. - - * The first step is ((R) ? 1 : -1). Given an expression R, of - integral or boolean or floating-point type, this yields an - expression of integral type, whose value is later verified to be - constant and nonnegative. - - * Next this expression W is wrapped in a type - struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }. - If W is negative, this yields a compile-time error. No compiler can - deal with a bit-field of negative size. - - One might think that an array size check would have the same - effect, that is, that the type struct { unsigned int dummy[W]; } - would work as well. However, inside a function, some compilers - (such as C++ compilers and GNU C) allow local parameters and - variables inside array size expressions. With these compilers, - an array size check would not properly diagnose this misuse of - the verify macro: - - void function (int n) { verify (n < 0); } - - * For the verify macro, the struct verify_type__ will need to - somehow be embedded into a declaration. To be portable, this - declaration must declare an object, a constant, a function, or a - typedef name. If the declared entity uses the type directly, - such as in - - struct dummy {...}; - typedef struct {...} dummy; - extern struct {...} *dummy; - extern void dummy (struct {...} *); - extern struct {...} *dummy (void); - - two uses of the verify macro would yield colliding declarations - if the entity names are not disambiguated. A workaround is to - attach the current line number to the entity name: - - #define GL_CONCAT0(x, y) x##y - #define GL_CONCAT(x, y) GL_CONCAT0 (x, y) - extern struct {...} * GL_CONCAT(dummy,__LINE__); - - But this has the problem that two invocations of verify from - within the same macro would collide, since the __LINE__ value - would be the same for both invocations. - - A solution is to use the sizeof operator. It yields a number, - getting rid of the identity of the type. Declarations like - - extern int dummy [sizeof (struct {...})]; - extern void dummy (int [sizeof (struct {...})]); - extern int (*dummy (void)) [sizeof (struct {...})]; - - can be repeated. - - * Should the implementation use a named struct or an unnamed struct? - Which of the following alternatives can be used? - - extern int dummy [sizeof (struct {...})]; - extern int dummy [sizeof (struct verify_type__ {...})]; - extern void dummy (int [sizeof (struct {...})]); - extern void dummy (int [sizeof (struct verify_type__ {...})]); - extern int (*dummy (void)) [sizeof (struct {...})]; - extern int (*dummy (void)) [sizeof (struct verify_type__ {...})]; - - In the second and sixth case, the struct type is exported to the - outer scope; two such declarations therefore collide. GCC warns - about the first, third, and fourth cases. So the only remaining - possibility is the fifth case: - - extern int (*dummy (void)) [sizeof (struct {...})]; - - * This implementation exploits the fact that GCC does not warn about - the last declaration mentioned above. If a future version of GCC - introduces a warning for this, the problem could be worked around - by using code specialized to GCC, e.g.,: - - #if 4 <= __GNUC__ - # define verify(R) \ - extern int (* verify_function__ (void)) \ - [__builtin_constant_p (R) && (R) ? 1 : -1] - #endif - - * In C++, any struct definition inside sizeof is invalid. - Use a template type to work around the problem. */ - - -/* Verify requirement R at compile-time, as an integer constant expression. - Return 1. */ - -# ifdef __cplusplus -template - struct verify_type__ { unsigned int verify_error_if_negative_size__: w; }; -# define verify_true(R) \ - (!!sizeof (verify_type__<(R) ? 1 : -1>)) -# else -# define verify_true(R) \ - (!!sizeof \ - (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; })) -# endif - -/* Verify requirement R at compile-time, as a declaration without a - trailing ';'. */ - -# define verify(R) extern int (* verify_function__ (void)) [verify_true (R)] - -#endif diff --git a/src/bin/m4/lib/verror.c b/src/bin/m4/lib/verror.c deleted file mode 100644 index 531e4edb5f..0000000000 --- a/src/bin/m4/lib/verror.c +++ /dev/null @@ -1,77 +0,0 @@ -/* va_list error handler for noninteractive utilities - Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Eric Blake. */ - -#include - -#include "verror.h" -#include "xvasprintf.h" - -#include -#include -#include - -#if ENABLE_NLS -# include "gettext.h" -#endif - -#ifndef _ -# define _(String) String -#endif - -/* Print a message with `vfprintf (stderr, FORMAT, ARGS)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. - Use the globals error_print_progname and error_message_count similarly - to error(). */ -void -verror (int status, int errnum, const char *format, va_list args) -{ - verror_at_line (status, errnum, NULL, 0, format, args); -} - -/* Print a message with `vfprintf (stderr, FORMAT, ARGS)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. - If FNAME is not NULL, prepend the message with `FNAME:LINENO:'. - Use the globals error_print_progname, error_message_count, and - error_one_per_line similarly to error_at_line(). */ -void -verror_at_line (int status, int errnum, const char *file, - unsigned int line_number, const char *format, va_list args) -{ - char *message = xvasprintf (format, args); - if (message) - { - /* Until http://sourceware.org/bugzilla/show_bug.cgi?id=2997 is fixed, - glibc violates GNU Coding Standards when the file argument to - error_at_line is NULL. */ - if (file) - error_at_line (status, errnum, file, line_number, "%s", message); - else - error (status, errnum, "%s", message); - } - else - { - /* EOVERFLOW, EINVAL, and EILSEQ from xvasprintf are signs of - serious programmer errors. */ - error (0, errno, _("unable to display error message")); - abort (); - } - free (message); -} diff --git a/src/bin/m4/lib/verror.h b/src/bin/m4/lib/verror.h deleted file mode 100644 index 625ef102ee..0000000000 --- a/src/bin/m4/lib/verror.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Declaration for va_list error-reporting function - Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _VERROR_H -#define _VERROR_H 1 - -#include "error.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Print a message with `vfprintf (stderr, FORMAT, ARGS)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. - Use the globals error_print_progname and error_message_count similarly - to error(). */ - -extern void verror (int __status, int __errnum, const char *__format, - va_list __args) - __attribute__ ((__format__ (__printf__, 3, 0))); - -/* Print a message with `vfprintf (stderr, FORMAT, ARGS)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. - If FNAME is not NULL, prepend the message with `FNAME:LINENO:'. - Use the globals error_print_progname, error_message_count, and - error_one_per_line similarly to error_at_line(). */ - -extern void verror_at_line (int __status, int __errnum, const char *__fname, - unsigned int __lineno, const char *__format, - va_list __args) - __attribute__ ((__format__ (__printf__, 5, 0))); - -#ifdef __cplusplus -} -#endif - -#endif /* verror.h */ diff --git a/src/bin/m4/lib/wcwidth.h b/src/bin/m4/lib/wcwidth.h deleted file mode 100644 index 83da8fb0fb..0000000000 --- a/src/bin/m4/lib/wcwidth.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Determine the number of screen columns needed for a character. - Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _gl_WCWIDTH_H -#define _gl_WCWIDTH_H - -#if HAVE_WCHAR_T - -/* Get wcwidth if available, along with wchar_t. */ -# if HAVE_WCHAR_H -/* Tru64 with Desktop Toolkit C has a bug: must be included before - . - BSD/OS 4.1 has a bug: and must be included before - . */ -# include -# include -# include -# endif - -/* Get iswprint. */ -# if HAVE_WCTYPE_H -# include -# endif -# if !defined iswprint && !HAVE_ISWPRINT -static inline int -# if HAVE_WINT_T -iswprint (wint_t wc) -# else -iswprint (int wc) -# endif -{ - return (wc >= 0 && wc < 128 - ? wc >= ' ' && wc <= '~' - : 1); -} -# define iswprint iswprint -# endif - -# ifndef HAVE_DECL_WCWIDTH -"this configure-time declaration test was not run" -# endif -# ifndef wcwidth -# if !HAVE_WCWIDTH - -/* wcwidth doesn't exist, so assume all printable characters have - width 1. */ -static inline int -wcwidth (wchar_t wc) -{ - return wc == 0 ? 0 : iswprint (wc) ? 1 : -1; -} - -# elif !HAVE_DECL_WCWIDTH - -/* wcwidth exists but is not declared. */ -extern -# ifdef __cplusplus -"C" -# endif -int wcwidth (int /* actually wchar_t */); - -# endif -# endif - -#endif /* HAVE_WCHAR_H */ - -#endif /* _gl_WCWIDTH_H */ diff --git a/src/bin/m4/lib/xalloc-die.c b/src/bin/m4/lib/xalloc-die.c deleted file mode 100644 index 090f060df7..0000000000 --- a/src/bin/m4/lib/xalloc-die.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Report a memory allocation failure and exit. - - Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "xalloc.h" - -#include - -#include "error.h" -#include "exitfail.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -void -xalloc_die (void) -{ - error (exit_failure, 0, "%s", _("memory exhausted")); - - /* The `noreturn' cannot be given to error, since it may return if - its first argument is 0. To help compilers understand the - xalloc_die does not return, call abort. Also, the abort is a - safety feature if exit_failure is 0 (which shouldn't happen). */ - abort (); -} diff --git a/src/bin/m4/lib/xalloc.h b/src/bin/m4/lib/xalloc.h deleted file mode 100644 index 17ab514218..0000000000 --- a/src/bin/m4/lib/xalloc.h +++ /dev/null @@ -1,267 +0,0 @@ -/* xalloc.h -- malloc with out-of-memory checking - - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2003, 2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef XALLOC_H_ -# define XALLOC_H_ - -# include - - -# ifdef __cplusplus -extern "C" { -# endif - - -# ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ -# define __attribute__(x) -# endif -# endif - -# ifndef ATTRIBUTE_NORETURN -# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -# endif - -/* This function is always triggered when memory is exhausted. - It must be defined by the application, either explicitly - or by using gnulib's xalloc-die module. This is the - function to call when one wants the program to die because of a - memory allocation failure. */ -extern void xalloc_die (void) ATTRIBUTE_NORETURN; - -void *xmalloc (size_t s); -void *xzalloc (size_t s); -void *xcalloc (size_t n, size_t s); -void *xrealloc (void *p, size_t s); -void *x2realloc (void *p, size_t *pn); -void *xmemdup (void const *p, size_t s); -char *xstrdup (char const *str); - -/* Return 1 if an array of N objects, each of size S, cannot exist due - to size arithmetic overflow. S must be positive and N must be - nonnegative. This is a macro, not an inline function, so that it - works correctly even when SIZE_MAX < N. - - By gnulib convention, SIZE_MAX represents overflow in size - calculations, so the conservative dividend to use here is - SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. - However, malloc (SIZE_MAX) fails on all known hosts where - sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for - exactly-SIZE_MAX allocations on such hosts; this avoids a test and - branch when S is known to be 1. */ -# define xalloc_oversized(n, s) \ - ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) - - -/* In the following macros, T must be an elementary or structure/union or - typedef'ed type, or a pointer to such a type. To apply one of the - following macros to a function pointer or array type, you need to typedef - it first and use the typedef name. */ - -/* Allocate an object of type T dynamically, with error checking. */ -/* extern t *XMALLOC (typename t); */ -# define XMALLOC(t) ((t *) xmalloc (sizeof (t))) - -/* Allocate memory for N elements of type T, with error checking. */ -/* extern t *XNMALLOC (size_t n, typename t); */ -# define XNMALLOC(n, t) \ - ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t)))) - -/* Allocate an object of type T dynamically, with error checking, - and zero it. */ -/* extern t *XZALLOC (typename t); */ -# define XZALLOC(t) ((t *) xzalloc (sizeof (t))) - -/* Allocate memory for N elements of type T, with error checking, - and zero it. */ -/* extern t *XCALLOC (size_t n, typename t); */ -# define XCALLOC(n, t) \ - ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t)))) - - -# if HAVE_INLINE -# define static_inline static inline -# else - void *xnmalloc (size_t n, size_t s); - void *xnrealloc (void *p, size_t n, size_t s); - void *x2nrealloc (void *p, size_t *pn, size_t s); - char *xcharalloc (size_t n); -# endif - -# ifdef static_inline - -/* Allocate an array of N objects, each with S bytes of memory, - dynamically, with error checking. S must be nonzero. */ - -static_inline void * -xnmalloc (size_t n, size_t s) -{ - if (xalloc_oversized (n, s)) - xalloc_die (); - return xmalloc (n * s); -} - -/* Change the size of an allocated block of memory P to an array of N - objects each of S bytes, with error checking. S must be nonzero. */ - -static_inline void * -xnrealloc (void *p, size_t n, size_t s) -{ - if (xalloc_oversized (n, s)) - xalloc_die (); - return xrealloc (p, n * s); -} - -/* If P is null, allocate a block of at least *PN such objects; - otherwise, reallocate P so that it contains more than *PN objects - each of S bytes. *PN must be nonzero unless P is null, and S must - be nonzero. Set *PN to the new number of objects, and return the - pointer to the new block. *PN is never set to zero, and the - returned pointer is never null. - - Repeated reallocations are guaranteed to make progress, either by - allocating an initial block with a nonzero size, or by allocating a - larger block. - - In the following implementation, nonzero sizes are doubled so that - repeated reallocations have O(N log N) overall cost rather than - O(N**2) cost, but the specification for this function does not - guarantee that sizes are doubled. - - Here is an example of use: - - int *p = NULL; - size_t used = 0; - size_t allocated = 0; - - void - append_int (int value) - { - if (used == allocated) - p = x2nrealloc (p, &allocated, sizeof *p); - p[used++] = value; - } - - This causes x2nrealloc to allocate a block of some nonzero size the - first time it is called. - - To have finer-grained control over the initial size, set *PN to a - nonzero value before calling this function with P == NULL. For - example: - - int *p = NULL; - size_t used = 0; - size_t allocated = 0; - size_t allocated1 = 1000; - - void - append_int (int value) - { - if (used == allocated) - { - p = x2nrealloc (p, &allocated1, sizeof *p); - allocated = allocated1; - } - p[used++] = value; - } - - */ - -static_inline void * -x2nrealloc (void *p, size_t *pn, size_t s) -{ - size_t n = *pn; - - if (! p) - { - if (! n) - { - /* The approximate size to use for initial small allocation - requests, when the invoking code specifies an old size of - zero. 64 bytes is the largest "small" request for the - GNU C library malloc. */ - enum { DEFAULT_MXFAST = 64 }; - - n = DEFAULT_MXFAST / s; - n += !n; - } - } - else - { - if (((size_t) -1) / 2 / s < n) - xalloc_die (); - n *= 2; - } - - *pn = n; - return xrealloc (p, n * s); -} - -/* Return a pointer to a new buffer of N bytes. This is like xmalloc, - except it returns char *. */ - -static_inline char * -xcharalloc (size_t n) -{ - return XNMALLOC (n, char); -} - -# endif - -# ifdef __cplusplus -} - -/* C++ does not allow conversions from void * to other pointer types - without a cast. Use templates to work around the problem when - possible. */ - -template inline T * -xrealloc (T *p, size_t s) -{ - return (T *) xrealloc ((void *) p, s); -} - -template inline T * -xnrealloc (T *p, size_t n, size_t s) -{ - return (T *) xnrealloc ((void *) p, n, s); -} - -template inline T * -x2realloc (T *p, size_t *pn) -{ - return (T *) x2realloc ((void *) p, pn); -} - -template inline T * -x2nrealloc (T *p, size_t *pn, size_t s) -{ - return (T *) x2nrealloc ((void *) p, pn, s); -} - -template inline T * -xmemdup (T const *p, size_t s) -{ - return (T *) xmemdup ((void const *) p, s); -} - -# endif - - -#endif /* !XALLOC_H_ */ diff --git a/src/bin/m4/lib/xallocsa.c b/src/bin/m4/lib/xallocsa.c deleted file mode 100644 index c69128a365..0000000000 --- a/src/bin/m4/lib/xallocsa.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Safe automatic memory allocation with out of memory checking. - Copyright (C) 2003, 2006 Free Software Foundation, Inc. - Written by Bruno Haible , 2003. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "xallocsa.h" - -#include "xalloc.h" - -void * -xmallocsa (size_t n) -{ - void *p; - - p = mallocsa (n); - if (p == NULL) - xalloc_die (); - return p; -} diff --git a/src/bin/m4/lib/xallocsa.h b/src/bin/m4/lib/xallocsa.h deleted file mode 100644 index baede95775..0000000000 --- a/src/bin/m4/lib/xallocsa.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Safe automatic memory allocation with out of memory checking. - Copyright (C) 2003, 2005 Free Software Foundation, Inc. - Written by Bruno Haible , 2003. - - 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _XALLOCSA_H -#define _XALLOCSA_H - -#include "allocsa.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* xallocsa(N) is a checking safe variant of alloca(N). It allocates N bytes - of memory allocated on the stack, that must be freed using freesa() before - the function returns. Upon failure, it exits with an error message. */ -#if HAVE_ALLOCA -# define xallocsa(N) \ - ((N) < 4032 - sa_increment \ - ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \ - : xmallocsa (N)) -extern void * xmallocsa (size_t n); -#else -# define xallocsa(N) \ - xmalloc (N) -#endif - -/* Maybe we should also define a variant - xnallocsa (size_t n, size_t s) - behaves like xallocsa (n * s) - If this would be useful in your application. please speak up. */ - - -#ifdef __cplusplus -} -#endif - - -#endif /* _XALLOCSA_H */ diff --git a/src/bin/m4/lib/xasprintf.c b/src/bin/m4/lib/xasprintf.c deleted file mode 100644 index cf1b8a5ee4..0000000000 --- a/src/bin/m4/lib/xasprintf.c +++ /dev/null @@ -1,34 +0,0 @@ -/* vasprintf and asprintf with out-of-memory checking. - Copyright (C) 1999, 2002-2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "xvasprintf.h" - -char * -xasprintf (const char *format, ...) -{ - va_list args; - char *result; - - va_start (args, format); - result = xvasprintf (format, args); - va_end (args); - - return result; -} diff --git a/src/bin/m4/lib/xmalloc.c b/src/bin/m4/lib/xmalloc.c deleted file mode 100644 index 318e0ddb5a..0000000000 --- a/src/bin/m4/lib/xmalloc.c +++ /dev/null @@ -1,123 +0,0 @@ -/* xmalloc.c -- malloc with out of memory checking - - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2002, 2003, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#if ! HAVE_INLINE -# define static_inline -#endif -#include "xalloc.h" -#undef static_inline - -#include -#include - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -/* 1 if calloc is known to be compatible with GNU calloc. This - matters if we are not also using the calloc module, which defines - HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */ -#if defined HAVE_CALLOC || defined __GLIBC__ -enum { HAVE_GNU_CALLOC = 1 }; -#else -enum { HAVE_GNU_CALLOC = 0 }; -#endif - -/* Allocate N bytes of memory dynamically, with error checking. */ - -void * -xmalloc (size_t n) -{ - void *p = malloc (n); - if (!p && n != 0) - xalloc_die (); - return p; -} - -/* Change the size of an allocated block of memory P to N bytes, - with error checking. */ - -void * -xrealloc (void *p, size_t n) -{ - p = realloc (p, n); - if (!p && n != 0) - xalloc_die (); - return p; -} - -/* If P is null, allocate a block of at least *PN bytes; otherwise, - reallocate P so that it contains more than *PN bytes. *PN must be - nonzero unless P is null. Set *PN to the new block's size, and - return the pointer to the new block. *PN is never set to zero, and - the returned pointer is never null. */ - -void * -x2realloc (void *p, size_t *pn) -{ - return x2nrealloc (p, pn, 1); -} - -/* Allocate S bytes of zeroed memory dynamically, with error checking. - There's no need for xnzalloc (N, S), since it would be equivalent - to xcalloc (N, S). */ - -void * -xzalloc (size_t s) -{ - return memset (xmalloc (s), 0, s); -} - -/* Allocate zeroed memory for N elements of S bytes, with error - checking. S must be nonzero. */ - -void * -xcalloc (size_t n, size_t s) -{ - void *p; - /* Test for overflow, since some calloc implementations don't have - proper overflow checks. But omit overflow and size-zero tests if - HAVE_GNU_CALLOC, since GNU calloc catches overflow and never - returns NULL if successful. */ - if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s)) - || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0))) - xalloc_die (); - return p; -} - -/* Clone an object P of size S, with error checking. There's no need - for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any - need for an arithmetic overflow check. */ - -void * -xmemdup (void const *p, size_t s) -{ - return memcpy (xmalloc (s), p, s); -} - -/* Clone STRING. */ - -char * -xstrdup (char const *string) -{ - return xmemdup (string, strlen (string) + 1); -} diff --git a/src/bin/m4/lib/xsize.h b/src/bin/m4/lib/xsize.h deleted file mode 100644 index 341fb16ca7..0000000000 --- a/src/bin/m4/lib/xsize.h +++ /dev/null @@ -1,108 +0,0 @@ -/* xsize.h -- Checked size_t computations. - - Copyright (C) 2003 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _XSIZE_H -#define _XSIZE_H - -/* Get size_t. */ -#include - -/* Get SIZE_MAX. */ -#include -#if HAVE_STDINT_H -# include -#endif - -/* The size of memory objects is often computed through expressions of - type size_t. Example: - void* p = malloc (header_size + n * element_size). - These computations can lead to overflow. When this happens, malloc() - returns a piece of memory that is way too small, and the program then - crashes while attempting to fill the memory. - To avoid this, the functions and macros in this file check for overflow. - The convention is that SIZE_MAX represents overflow. - malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc - implementation that uses mmap --, it's recommended to use size_overflow_p() - or size_in_bounds_p() before invoking malloc(). - The example thus becomes: - size_t size = xsum (header_size, xtimes (n, element_size)); - void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); -*/ - -/* Convert an arbitrary value >= 0 to type size_t. */ -#define xcast_size_t(N) \ - ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) - -/* Sum of two sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xsum (size_t size1, size_t size2) -{ - size_t sum = size1 + size2; - return (sum >= size1 ? sum : SIZE_MAX); -} - -/* Sum of three sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xsum3 (size_t size1, size_t size2, size_t size3) -{ - return xsum (xsum (size1, size2), size3); -} - -/* Sum of four sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) -{ - return xsum (xsum (xsum (size1, size2), size3), size4); -} - -/* Maximum of two sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xmax (size_t size1, size_t size2) -{ - /* No explicit check is needed here, because for any n: - max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ - return (size1 >= size2 ? size1 : size2); -} - -/* Multiplication of a count with an element size, with overflow check. - The count must be >= 0 and the element size must be > 0. - This is a macro, not an inline function, so that it works correctly even - when N is of a wider tupe and N > SIZE_MAX. */ -#define xtimes(N, ELSIZE) \ - ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) - -/* Check for overflow. */ -#define size_overflow_p(SIZE) \ - ((SIZE) == SIZE_MAX) -/* Check against overflow. */ -#define size_in_bounds_p(SIZE) \ - ((SIZE) != SIZE_MAX) - -#endif /* _XSIZE_H */ diff --git a/src/bin/m4/lib/xvasprintf.c b/src/bin/m4/lib/xvasprintf.c deleted file mode 100644 index b68442764d..0000000000 --- a/src/bin/m4/lib/xvasprintf.c +++ /dev/null @@ -1,116 +0,0 @@ -/* vasprintf and asprintf with out-of-memory checking. - Copyright (C) 1999, 2002-2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "xvasprintf.h" - -#include -#include -#include - -#include "vasprintf.h" -#include "xalloc.h" - -/* Checked size_t computations. */ -#include "xsize.h" - -/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ -#ifndef EOVERFLOW -# define EOVERFLOW E2BIG -#endif - -static inline char * -xstrcat (size_t argcount, va_list args) -{ - char *result; - va_list ap; - size_t totalsize; - size_t i; - char *p; - - /* Determine the total size. */ - totalsize = 0; - va_copy (ap, args); - for (i = argcount; i > 0; i--) - { - const char *next = va_arg (ap, const char *); - totalsize = xsum (totalsize, strlen (next)); - } - va_end (ap); - - /* Test for overflow in the summing pass above or in (totalsize + 1) below. - Also, don't return a string longer than INT_MAX, for consistency with - vasprintf(). */ - if (totalsize == SIZE_MAX || totalsize > INT_MAX) - { - errno = EOVERFLOW; - return NULL; - } - - /* Allocate and fill the result string. */ - result = XNMALLOC (totalsize + 1, char); - p = result; - for (i = argcount; i > 0; i--) - { - const char *next = va_arg (args, const char *); - size_t len = strlen (next); - memcpy (p, next, len); - p += len; - } - *p = '\0'; - - return result; -} - -char * -xvasprintf (const char *format, va_list args) -{ - char *result; - - /* Recognize the special case format = "%s...%s". It is a frequently used - idiom for string concatenation and needs to be fast. We don't want to - have a separate function xstrcat() for this purpose. */ - { - size_t argcount = 0; - const char *f; - - for (f = format;;) - { - if (*f == '\0') - /* Recognized the special case of string concatenation. */ - return xstrcat (argcount, args); - if (*f != '%') - break; - f++; - if (*f != 's') - break; - f++; - argcount++; - } - } - - if (vasprintf (&result, format, args) < 0) - { - if (errno == ENOMEM) - xalloc_die (); - return NULL; - } - - return result; -} diff --git a/src/bin/m4/lib/xvasprintf.h b/src/bin/m4/lib/xvasprintf.h deleted file mode 100644 index de55a9f0c8..0000000000 --- a/src/bin/m4/lib/xvasprintf.h +++ /dev/null @@ -1,57 +0,0 @@ -/* vasprintf and asprintf with out-of-memory checking. - Copyright (C) 2002-2004, 2006 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 2, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _XVASPRINTF_H -#define _XVASPRINTF_H - -/* Get va_list. */ -#include - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ -# define __attribute__(Spec) /* empty */ -# endif -/* The __-protected variants of `format' and `printf' attributes - are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __format__ format -# define __printf__ printf -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Write formatted output to a string dynamically allocated with malloc(), - and return it. Upon [ENOMEM] memory allocation error, call xalloc_die. - On some other error - - [EOVERFLOW] resulting string length is > INT_MAX, - - [EINVAL] invalid format string, - - [EILSEQ] error during conversion between wide and multibyte characters, - return NULL. */ -extern char *xasprintf (const char *format, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); -extern char *xvasprintf (const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 1, 0))); - -#ifdef __cplusplus -} -#endif - -#endif /* _XVASPRINTF_H */ diff --git a/src/bin/m4/src/Jamfile b/src/bin/m4/src/Jamfile deleted file mode 100644 index e19888352e..0000000000 --- a/src/bin/m4/src/Jamfile +++ /dev/null @@ -1,24 +0,0 @@ -SubDir HAIKU_TOP src bin m4 src ; - -#SubDirCcFlags -DHAVE_CONFIG_H -DPKGDATADIR=\'\"/etc\"\' -DLOCALEDIR=\'\"/etc/locale\"\' ; - -SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) lib ] ; -SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; - -BinCommand m4 : - builtin.c - debug.c - eval.c - format.c - freeze.c - input.c - m4.c - macro.c - output.c - path.c - #stackovf.c - symtab.c - : libm4.a - : m4.rdef -; - diff --git a/src/bin/m4/src/Makefile.am b/src/bin/m4/src/Makefile.am deleted file mode 100644 index ac7f1a82fc..0000000000 --- a/src/bin/m4/src/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -## This file is part of GNU M4. -## -## Copyright (C) 2006 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 2 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; see the file COPYING. If not, write to -## the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -## Boston, MA 02110-1301, USA. -## -## This file written by Eric Blake - -AUTOMAKE_OPTIONS = nostdinc -AM_CPPFLAGS = -I$(top_srcdir)/lib -I../lib -bin_PROGRAMS = m4 -m4_SOURCES = m4.h m4.c builtin.c debug.c eval.c format.c freeze.c input.c \ -macro.c output.c path.c symtab.c -if STACKOVF -m4_SOURCES += stackovf.c -endif -m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) diff --git a/src/bin/m4/src/Makefile.in b/src/bin/m4/src/Makefile.in deleted file mode 100644 index c73eeebd0e..0000000000 --- a/src/bin/m4/src/Makefile.in +++ /dev/null @@ -1,510 +0,0 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This Makefile.in 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. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -bin_PROGRAMS = m4$(EXEEXT) -@STACKOVF_TRUE@am__append_1 = stackovf.c -subdir = src -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ - $(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/allocsa.m4 \ - $(top_srcdir)/m4/cloexec.m4 $(top_srcdir)/m4/close-stream.m4 \ - $(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/config-h.m4 $(top_srcdir)/m4/eealloc.m4 \ - $(top_srcdir)/m4/eoverflow.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/fatal-signal.m4 $(top_srcdir)/m4/fpending.m4 \ - $(top_srcdir)/m4/free.m4 $(top_srcdir)/m4/getopt.m4 \ - $(top_srcdir)/m4/gl_list.m4 $(top_srcdir)/m4/gnulib-comp.m4 \ - $(top_srcdir)/m4/inline.m4 $(top_srcdir)/m4/intmax_t.m4 \ - $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/longdouble.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mbchar.m4 \ - $(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \ - $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/memchr.m4 \ - $(top_srcdir)/m4/mkdtemp.m4 $(top_srcdir)/m4/mkstemp.m4 \ - $(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/quotearg.m4 \ - $(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/sig_atomic_t.m4 \ - $(top_srcdir)/m4/signalblocking.m4 \ - $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/ssize_t.m4 \ - $(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \ - $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ - $(top_srcdir)/m4/stdio-safer.m4 \ - $(top_srcdir)/m4/stdlib-safer.m4 $(top_srcdir)/m4/strcase.m4 \ - $(top_srcdir)/m4/strstr.m4 $(top_srcdir)/m4/strtol.m4 \ - $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/tempname.m4 \ - $(top_srcdir)/m4/tmpdir.m4 $(top_srcdir)/m4/ulonglong.m4 \ - $(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \ - $(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/vasnprintf.m4 \ - $(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wcwidth.m4 $(top_srcdir)/m4/wint_t.m4 \ - $(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/m4/xvasprintf.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/config.h -CONFIG_CLEAN_FILES = -am__installdirs = "$(DESTDIR)$(bindir)" -binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) -PROGRAMS = $(bin_PROGRAMS) -am__m4_SOURCES_DIST = m4.h m4.c builtin.c debug.c eval.c format.c \ - freeze.c input.c macro.c output.c path.c symtab.c stackovf.c -@STACKOVF_TRUE@am__objects_1 = stackovf.$(OBJEXT) -am_m4_OBJECTS = m4.$(OBJEXT) builtin.$(OBJEXT) debug.$(OBJEXT) \ - eval.$(OBJEXT) format.$(OBJEXT) freeze.$(OBJEXT) \ - input.$(OBJEXT) macro.$(OBJEXT) output.$(OBJEXT) \ - path.$(OBJEXT) symtab.$(OBJEXT) $(am__objects_1) -m4_OBJECTS = $(am_m4_OBJECTS) -am__DEPENDENCIES_1 = -m4_DEPENDENCIES = ../lib/libm4.a $(am__DEPENDENCIES_1) -DEFAULT_INCLUDES = -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(m4_SOURCES) -DIST_SOURCES = $(am__m4_SOURCES_DIST) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ABSOLUTE_STDINT_H = @ABSOLUTE_STDINT_H@ -ABSOLUTE_SYS_STAT_H = @ABSOLUTE_SYS_STAT_H@ -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -ALLOCA_H = @ALLOCA_H@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ -BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ -BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ -BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ -BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EOVERFLOW = @EOVERFLOW@ -EXEEXT = @EXEEXT@ -GETOPT_H = @GETOPT_H@ -GREP = @GREP@ -HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ -HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ -HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ -HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ -HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ -HAVE_STDINT_H = @HAVE_STDINT_H@ -HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ -HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ -HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ -HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ -HAVE_WCHAR_H = @HAVE_WCHAR_H@ -HAVE__BOOL = @HAVE__BOOL@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBM4_LIBDEPS = @LIBM4_LIBDEPS@ -LIBM4_LTLIBDEPS = @LIBM4_LTLIBDEPS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -M4_LIBOBJS = @M4_LIBOBJS@ -M4_LTLIBOBJS = @M4_LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ -SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ -STDBOOL_H = @STDBOOL_H@ -STDINT_H = @STDINT_H@ -STRIP = @STRIP@ -SYS_STAT_H = @SYS_STAT_H@ -UNISTD_H = @UNISTD_H@ -VERSION = @VERSION@ -WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ -WINT_T_SUFFIX = @WINT_T_SUFFIX@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = nostdinc -AM_CPPFLAGS = -I$(top_srcdir)/lib -I../lib -m4_SOURCES = m4.h m4.c builtin.c debug.c eval.c format.c freeze.c \ - input.c macro.c output.c path.c symtab.c $(am__append_1) -m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-binPROGRAMS: $(bin_PROGRAMS) - @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" - @list='$(bin_PROGRAMS)'; for p in $$list; do \ - p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - if test -f $$p \ - ; then \ - f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ - $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ - else :; fi; \ - done - -uninstall-binPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(bin_PROGRAMS)'; for p in $$list; do \ - f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ - rm -f "$(DESTDIR)$(bindir)/$$f"; \ - done - -clean-binPROGRAMS: - -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) -m4$(EXEEXT): $(m4_OBJECTS) $(m4_DEPENDENCIES) - @rm -f m4$(EXEEXT) - $(LINK) $(m4_OBJECTS) $(m4_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/format.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freeze.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m4.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macro.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stackovf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) -installdirs: - for dir in "$(DESTDIR)$(bindir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-binPROGRAMS clean-generic mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-exec-am: install-binPROGRAMS - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-binPROGRAMS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ - clean-generic ctags distclean distclean-compile \ - distclean-generic distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-binPROGRAMS \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-binPROGRAMS - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/bin/m4/src/builtin.c b/src/bin/m4/src/builtin.c deleted file mode 100644 index e7b120224d..0000000000 --- a/src/bin/m4/src/builtin.c +++ /dev/null @@ -1,2081 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2000, 2004, 2006 - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* Code for all builtin macros, initialization of symbol table, and - expansion of user defined macros. */ - -#include "m4.h" - -extern FILE *popen (); - -#include "regex.h" -#include "strstr.h" - -#if HAVE_SYS_WAIT_H -# include -#endif - -#define ARG(i) (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "") - -/* Initialization of builtin and predefined macros. The table - "builtin_tab" is both used for initialization, and by the "builtin" - builtin. */ - -#define DECLARE(name) \ - static void name (struct obstack *, int, token_data **) - -DECLARE (m4___file__); -DECLARE (m4___line__); -DECLARE (m4___program__); -DECLARE (m4_builtin); -DECLARE (m4_changecom); -DECLARE (m4_changequote); -#ifdef ENABLE_CHANGEWORD -DECLARE (m4_changeword); -#endif -DECLARE (m4_debugmode); -DECLARE (m4_debugfile); -DECLARE (m4_decr); -DECLARE (m4_define); -DECLARE (m4_defn); -DECLARE (m4_divert); -DECLARE (m4_divnum); -DECLARE (m4_dnl); -DECLARE (m4_dumpdef); -DECLARE (m4_errprint); -DECLARE (m4_esyscmd); -DECLARE (m4_eval); -DECLARE (m4_format); -DECLARE (m4_ifdef); -DECLARE (m4_ifelse); -DECLARE (m4_include); -DECLARE (m4_incr); -DECLARE (m4_index); -DECLARE (m4_indir); -DECLARE (m4_len); -DECLARE (m4_m4exit); -DECLARE (m4_m4wrap); -DECLARE (m4_maketemp); -DECLARE (m4_mkstemp); -DECLARE (m4_patsubst); -DECLARE (m4_popdef); -DECLARE (m4_pushdef); -DECLARE (m4_regexp); -DECLARE (m4_shift); -DECLARE (m4_sinclude); -DECLARE (m4_substr); -DECLARE (m4_syscmd); -DECLARE (m4_sysval); -DECLARE (m4_traceoff); -DECLARE (m4_traceon); -DECLARE (m4_translit); -DECLARE (m4_undefine); -DECLARE (m4_undivert); - -#undef DECLARE - -static builtin -builtin_tab[] = -{ - - /* name GNUext macros blind function */ - - { "__file__", true, false, false, m4___file__ }, - { "__line__", true, false, false, m4___line__ }, - { "__program__", true, false, false, m4___program__ }, - { "builtin", true, true, true, m4_builtin }, - { "changecom", false, false, false, m4_changecom }, - { "changequote", false, false, false, m4_changequote }, -#ifdef ENABLE_CHANGEWORD - { "changeword", true, false, true, m4_changeword }, -#endif - { "debugmode", true, false, false, m4_debugmode }, - { "debugfile", true, false, false, m4_debugfile }, - { "decr", false, false, true, m4_decr }, - { "define", false, true, true, m4_define }, - { "defn", false, false, true, m4_defn }, - { "divert", false, false, false, m4_divert }, - { "divnum", false, false, false, m4_divnum }, - { "dnl", false, false, false, m4_dnl }, - { "dumpdef", false, false, false, m4_dumpdef }, - { "errprint", false, false, true, m4_errprint }, - { "esyscmd", true, false, true, m4_esyscmd }, - { "eval", false, false, true, m4_eval }, - { "format", true, false, true, m4_format }, - { "ifdef", false, false, true, m4_ifdef }, - { "ifelse", false, false, true, m4_ifelse }, - { "include", false, false, true, m4_include }, - { "incr", false, false, true, m4_incr }, - { "index", false, false, true, m4_index }, - { "indir", true, true, true, m4_indir }, - { "len", false, false, true, m4_len }, - { "m4exit", false, false, false, m4_m4exit }, - { "m4wrap", false, false, true, m4_m4wrap }, - { "maketemp", false, false, true, m4_maketemp }, - { "mkstemp", false, false, true, m4_mkstemp }, - { "patsubst", true, false, true, m4_patsubst }, - { "popdef", false, false, true, m4_popdef }, - { "pushdef", false, true, true, m4_pushdef }, - { "regexp", true, false, true, m4_regexp }, - { "shift", false, false, true, m4_shift }, - { "sinclude", false, false, true, m4_sinclude }, - { "substr", false, false, true, m4_substr }, - { "syscmd", false, false, true, m4_syscmd }, - { "sysval", false, false, false, m4_sysval }, - { "traceoff", false, false, false, m4_traceoff }, - { "traceon", false, false, false, m4_traceon }, - { "translit", false, false, true, m4_translit }, - { "undefine", false, false, true, m4_undefine }, - { "undivert", false, false, false, m4_undivert }, - - { 0, false, false, false, 0 }, - - /* placeholder is intentionally stuck after the table end delimiter, - so that we can easily find it, while not treating it as a real - builtin. */ - { "placeholder", true, false, false, m4_placeholder }, -}; - -static predefined const -predefined_tab[] = -{ -#if UNIX - { "unix", "__unix__", "" }, -#elif W32_NATIVE - { "windows", "__windows__", "" }, -#elif OS2 - { "os2", "__os2__", "" }, -#else -# warning Platform macro not provided -#endif - { NULL, "__gnu__", "" }, - - { NULL, NULL, NULL }, -}; - -/*----------------------------------------. -| Find the builtin, which lives on ADDR. | -`----------------------------------------*/ - -const builtin * -find_builtin_by_addr (builtin_func *func) -{ - const builtin *bp; - - for (bp = &builtin_tab[0]; bp->name != NULL; bp++) - if (bp->func == func) - return bp; - if (func == m4_placeholder) - return bp + 1; - return NULL; -} - -/*----------------------------------------------------------. -| Find the builtin, which has NAME. On failure, return the | -| placeholder builtin. | -`----------------------------------------------------------*/ - -const builtin * -find_builtin_by_name (const char *name) -{ - const builtin *bp; - - for (bp = &builtin_tab[0]; bp->name != NULL; bp++) - if (strcmp (bp->name, name) == 0) - return bp; - return bp + 1; -} - -/*-------------------------------------------------------------------------. -| Install a builtin macro with name NAME, bound to the C function given in | -| BP. MODE is SYMBOL_INSERT or SYMBOL_PUSHDEF. TRACED defines whether | -| NAME is to be traced. | -`-------------------------------------------------------------------------*/ - -void -define_builtin (const char *name, const builtin *bp, symbol_lookup mode) -{ - symbol *sym; - - sym = lookup_symbol (name, mode); - SYMBOL_TYPE (sym) = TOKEN_FUNC; - SYMBOL_MACRO_ARGS (sym) = bp->groks_macro_args; - SYMBOL_BLIND_NO_ARGS (sym) = bp->blind_if_no_args; - SYMBOL_FUNC (sym) = bp->func; -} - -/*-------------------------------------------------------------------------. -| Define a predefined or user-defined macro, with name NAME, and expansion | -| TEXT. MODE destinguishes between the "define" and the "pushdef" case. | -| It is also used from main (). | -`-------------------------------------------------------------------------*/ - -void -define_user_macro (const char *name, const char *text, symbol_lookup mode) -{ - symbol *s; - - s = lookup_symbol (name, mode); - if (SYMBOL_TYPE (s) == TOKEN_TEXT) - free (SYMBOL_TEXT (s)); - - SYMBOL_TYPE (s) = TOKEN_TEXT; - SYMBOL_TEXT (s) = xstrdup (text ? text : ""); -} - -/*-----------------------------------------------. -| Initialize all builtin and predefined macros. | -`-----------------------------------------------*/ - -void -builtin_init (void) -{ - const builtin *bp; - const predefined *pp; - char *string; - - for (bp = &builtin_tab[0]; bp->name != NULL; bp++) - if (!no_gnu_extensions || !bp->gnu_extension) - { - if (prefix_all_builtins) - { - string = (char *) xmalloc (strlen (bp->name) + 4); - strcpy (string, "m4_"); - strcat (string, bp->name); - define_builtin (string, bp, SYMBOL_INSERT); - free (string); - } - else - define_builtin (bp->name, bp, SYMBOL_INSERT); - } - - for (pp = &predefined_tab[0]; pp->func != NULL; pp++) - if (no_gnu_extensions) - { - if (pp->unix_name != NULL) - define_user_macro (pp->unix_name, pp->func, SYMBOL_INSERT); - } - else - { - if (pp->gnu_name != NULL) - define_user_macro (pp->gnu_name, pp->func, SYMBOL_INSERT); - } -} - -/*------------------------------------------------------------------------. -| Give friendly warnings if a builtin macro is passed an inappropriate | -| number of arguments. NAME is macro name for messages, ARGC is actual | -| number of arguments, MIN is the minimum number of acceptable arguments, | -| negative if not applicable, MAX is the maximum number, negative if not | -| applicable. | -`------------------------------------------------------------------------*/ - -static bool -bad_argc (token_data *name, int argc, int min, int max) -{ - bool isbad = false; - - if (min > 0 && argc < min) - { - if (!suppress_warnings) - M4ERROR ((warning_status, 0, - "Warning: too few arguments to builtin `%s'", - TOKEN_DATA_TEXT (name))); - isbad = true; - } - else if (max > 0 && argc > max && !suppress_warnings) - M4ERROR ((warning_status, 0, - "Warning: excess arguments to builtin `%s' ignored", - TOKEN_DATA_TEXT (name))); - - return isbad; -} - -/*--------------------------------------------------------------------------. -| The function numeric_arg () converts ARG to an int pointed to by VALUEP. | -| If the conversion fails, print error message for macro MACRO. Return | -| true iff conversion succeeds. | -`--------------------------------------------------------------------------*/ - -static bool -numeric_arg (token_data *macro, const char *arg, int *valuep) -{ - char *endp; - - if (*arg == '\0') - { - *valuep = 0; - M4ERROR ((warning_status, 0, - "empty string treated as 0 in builtin `%s'", - TOKEN_DATA_TEXT (macro))); - } - else - { - errno = 0; - *valuep = strtol (arg, &endp, 10); - if (*endp != '\0') - { - M4ERROR ((warning_status, 0, - "non-numeric argument to builtin `%s'", - TOKEN_DATA_TEXT (macro))); - return false; - } - if (isspace (to_uchar (*arg))) - M4ERROR ((warning_status, 0, - "leading whitespace ignored in builtin `%s'", - TOKEN_DATA_TEXT (macro))); - else if (errno == ERANGE) - M4ERROR ((warning_status, 0, - "numeric overflow detected in builtin `%s'", - TOKEN_DATA_TEXT (macro))); - } - return true; -} - -/*------------------------------------------------------------------------. -| The function ntoa () converts VALUE to a signed ascii representation in | -| radix RADIX. | -`------------------------------------------------------------------------*/ - -/* Digits for number to ascii conversions. */ -static char const digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - -static const char * -ntoa (eval_t value, int radix) -{ - bool negative; - unsigned_eval_t uvalue; - static char str[256]; - char *s = &str[sizeof str]; - - *--s = '\0'; - - if (value < 0) - { - negative = true; - uvalue = (unsigned_eval_t) -value; - } - else - { - negative = false; - uvalue = (unsigned_eval_t) value; - } - - do - { - *--s = digits[uvalue % radix]; - uvalue /= radix; - } - while (uvalue > 0); - - if (negative) - *--s = '-'; - return s; -} - -/*----------------------------------------------------------------------. -| Format an int VAL, and stuff it into an obstack OBS. Used for macros | -| expanding to numbers. | -`----------------------------------------------------------------------*/ - -static void -shipout_int (struct obstack *obs, int val) -{ - const char *s; - - s = ntoa ((eval_t) val, 10); - obstack_grow (obs, s, strlen (s)); -} - -/*----------------------------------------------------------------------. -| Print ARGC arguments from the table ARGV to obstack OBS, separated by | -| SEP, and quoted by the current quotes, if QUOTED is true. | -`----------------------------------------------------------------------*/ - -static void -dump_args (struct obstack *obs, int argc, token_data **argv, - const char *sep, bool quoted) -{ - int i; - size_t len = strlen (sep); - - for (i = 1; i < argc; i++) - { - if (i > 1) - obstack_grow (obs, sep, len); - if (quoted) - obstack_grow (obs, lquote.string, lquote.length); - obstack_grow (obs, TOKEN_DATA_TEXT (argv[i]), - strlen (TOKEN_DATA_TEXT (argv[i]))); - if (quoted) - obstack_grow (obs, rquote.string, rquote.length); - } -} - -/* 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 m4_MACRONAME (struct 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. */ - -/* The first section are macros for definining, undefining, examining, - changing, ... other macros. */ - -/*-------------------------------------------------------------------------. -| The function define_macro is common for the builtins "define", | -| "undefine", "pushdef" and "popdef". ARGC and ARGV is as for the caller, | -| and MODE argument determines how the macro name is entered into the | -| symbol table. | -`-------------------------------------------------------------------------*/ - -static void -define_macro (int argc, token_data **argv, symbol_lookup mode) -{ - const builtin *bp; - - if (bad_argc (argv[0], argc, 2, 3)) - return; - - if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT) - { - M4ERROR ((warning_status, 0, - "Warning: %s: invalid macro name ignored", ARG (0))); - return; - } - - if (argc == 2) - { - define_user_macro (ARG (1), "", mode); - return; - } - - switch (TOKEN_DATA_TYPE (argv[2])) - { - case TOKEN_TEXT: - define_user_macro (ARG (1), ARG (2), mode); - break; - - case TOKEN_FUNC: - bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[2])); - if (bp == NULL) - return; - else - define_builtin (ARG (1), bp, mode); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad token data type in define_macro ()")); - abort (); - } -} - -static void -m4_define (struct obstack *obs, int argc, token_data **argv) -{ - define_macro (argc, argv, SYMBOL_INSERT); -} - -static void -m4_undefine (struct obstack *obs, int argc, token_data **argv) -{ - int i; - if (bad_argc (argv[0], argc, 2, -1)) - return; - for (i = 1; i < argc; i++) - lookup_symbol (ARG (i), SYMBOL_DELETE); -} - -static void -m4_pushdef (struct obstack *obs, int argc, token_data **argv) -{ - define_macro (argc, argv, SYMBOL_PUSHDEF); -} - -static void -m4_popdef (struct obstack *obs, int argc, token_data **argv) -{ - int i; - if (bad_argc (argv[0], argc, 2, -1)) - return; - for (i = 1; i < argc; i++) - lookup_symbol (ARG (i), SYMBOL_POPDEF); -} - -/*---------------------. -| Conditionals of m4. | -`---------------------*/ - -static void -m4_ifdef (struct obstack *obs, int argc, token_data **argv) -{ - symbol *s; - const char *result; - - if (bad_argc (argv[0], argc, 3, 4)) - return; - s = lookup_symbol (ARG (1), SYMBOL_LOOKUP); - - if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID) - result = ARG (2); - else if (argc >= 4) - result = ARG (3); - else - result = NULL; - - if (result != NULL) - obstack_grow (obs, result, strlen (result)); -} - -static void -m4_ifelse (struct obstack *obs, int argc, token_data **argv) -{ - const char *result; - token_data *argv0; - - if (argc == 2) - return; - - if (bad_argc (argv[0], argc, 4, -1)) - return; - else - /* Diagnose excess arguments if 5, 8, 11, etc., actual arguments. */ - bad_argc (argv[0], (argc + 2) % 3, -1, 1); - - argv0 = argv[0]; - argv++; - argc--; - - result = NULL; - while (result == NULL) - - if (strcmp (ARG (0), ARG (1)) == 0) - result = ARG (2); - - else - switch (argc) - { - case 3: - return; - - case 4: - case 5: - result = ARG (3); - break; - - default: - argc -= 3; - argv += 3; - } - - obstack_grow (obs, result, strlen (result)); -} - -/*---------------------------------------------------------------------. -| The function dump_symbol () is for use by "dumpdef". It builds up a | -| table of all defined, un-shadowed, symbols. | -`---------------------------------------------------------------------*/ - -/* The structure dump_symbol_data is used to pass the information needed - from call to call to dump_symbol. */ - -struct dump_symbol_data -{ - struct obstack *obs; /* obstack for table */ - symbol **base; /* base of table */ - int size; /* size of table */ -}; - -static void -dump_symbol (symbol *sym, void *arg) -{ - struct dump_symbol_data *data = (struct dump_symbol_data *) arg; - if (!SYMBOL_SHADOWED (sym) && SYMBOL_TYPE (sym) != TOKEN_VOID) - { - obstack_blank (data->obs, sizeof (symbol *)); - data->base = (symbol **) obstack_base (data->obs); - data->base[data->size++] = sym; - } -} - -/*------------------------------------------------------------------------. -| qsort comparison routine, for sorting the table made in m4_dumpdef (). | -`------------------------------------------------------------------------*/ - -static int -dumpdef_cmp (const void *s1, const void *s2) -{ - return strcmp (SYMBOL_NAME (* (symbol *const *) s1), - SYMBOL_NAME (* (symbol *const *) s2)); -} - -/*-------------------------------------------------------------------------. -| Implementation of "dumpdef" itself. It builds up a table of pointers to | -| symbols, sorts it and prints the sorted table. | -`-------------------------------------------------------------------------*/ - -static void -m4_dumpdef (struct obstack *obs, int argc, token_data **argv) -{ - symbol *s; - int i; - struct dump_symbol_data data; - const builtin *bp; - - data.obs = obs; - data.base = (symbol **) obstack_base (obs); - data.size = 0; - - if (argc == 1) - { - hack_all_symbols (dump_symbol, &data); - } - else - { - for (i = 1; i < argc; i++) - { - s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP); - if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID) - dump_symbol (s, &data); - else - M4ERROR ((warning_status, 0, - "undefined macro `%s'", TOKEN_DATA_TEXT (argv[i]))); - } - } - - /* Make table of symbols invisible to expand_macro (). */ - - obstack_finish (obs); - - qsort (data.base, data.size, sizeof (symbol *), dumpdef_cmp); - - for (; data.size > 0; --data.size, data.base++) - { - DEBUG_PRINT1 ("%s:\t", SYMBOL_NAME (data.base[0])); - - switch (SYMBOL_TYPE (data.base[0])) - { - case TOKEN_TEXT: - if (debug_level & DEBUG_TRACE_QUOTE) - DEBUG_PRINT3 ("%s%s%s\n", - lquote.string, SYMBOL_TEXT (data.base[0]), rquote.string); - else - DEBUG_PRINT1 ("%s\n", SYMBOL_TEXT (data.base[0])); - break; - - case TOKEN_FUNC: - bp = find_builtin_by_addr (SYMBOL_FUNC (data.base[0])); - if (bp == NULL) - { - M4ERROR ((warning_status, 0, "\ -INTERNAL ERROR: builtin not found in builtin table")); - abort (); - } - DEBUG_PRINT1 ("<%s>\n", bp->name); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad token data type in m4_dumpdef ()")); - abort (); - break; - } - } -} - -/*---------------------------------------------------------------------. -| 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. This | -| macro is not available in compatibility mode. | -`---------------------------------------------------------------------*/ - -static void -m4_builtin (struct obstack *obs, int argc, token_data **argv) -{ - const builtin *bp; - const char *name; - - if (bad_argc (argv[0], argc, 2, -1)) - return; - if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT) - { - M4ERROR ((warning_status, 0, - "Warning: %s: invalid macro name ignored", ARG (0))); - return; - } - - name = ARG (1); - bp = find_builtin_by_name (name); - if (bp->func == m4_placeholder) - M4ERROR ((warning_status, 0, - "undefined builtin `%s'", name)); - else - { - int i; - if (! bp->groks_macro_args) - for (i = 2; i < argc; i++) - if (TOKEN_DATA_TYPE (argv[i]) != TOKEN_TEXT) - { - TOKEN_DATA_TYPE (argv[i]) = TOKEN_TEXT; - TOKEN_DATA_TEXT (argv[i]) = (char *) ""; - } - bp->func (obs, argc - 1, argv + 1); - } -} - -/*------------------------------------------------------------------------. -| 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. This macro | -| is not available in compatibility mode. | -`------------------------------------------------------------------------*/ - -static void -m4_indir (struct obstack *obs, int argc, token_data **argv) -{ - symbol *s; - const char *name; - - if (bad_argc (argv[0], argc, 2, -1)) - return; - if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT) - { - M4ERROR ((warning_status, 0, - "Warning: %s: invalid macro name ignored", ARG (0))); - return; - } - - name = ARG (1); - s = lookup_symbol (name, SYMBOL_LOOKUP); - if (s == NULL || SYMBOL_TYPE (s) == TOKEN_VOID) - M4ERROR ((warning_status, 0, - "undefined macro `%s'", name)); - else - { - int i; - if (! SYMBOL_MACRO_ARGS (s)) - for (i = 2; i < argc; i++) - if (TOKEN_DATA_TYPE (argv[i]) != TOKEN_TEXT) - { - TOKEN_DATA_TYPE (argv[i]) = TOKEN_TEXT; - TOKEN_DATA_TEXT (argv[i]) = (char *) ""; - } - call_macro (s, argc - 1, argv + 1, obs); - } -} - -/*-------------------------------------------------------------------------. -| 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. | -`-------------------------------------------------------------------------*/ - -static void -m4_defn (struct obstack *obs, int argc, token_data **argv) -{ - symbol *s; - builtin_func *b; - - if (bad_argc (argv[0], argc, 2, 2)) - return; - - s = lookup_symbol (ARG (1), SYMBOL_LOOKUP); - if (s == NULL) - return; - - switch (SYMBOL_TYPE (s)) - { - case TOKEN_TEXT: - obstack_grow (obs, lquote.string, lquote.length); - obstack_grow (obs, SYMBOL_TEXT (s), strlen (SYMBOL_TEXT (s))); - obstack_grow (obs, rquote.string, rquote.length); - break; - - case TOKEN_FUNC: - b = SYMBOL_FUNC (s); - if (b == m4_placeholder) - M4ERROR ((warning_status, 0, "\ -builtin `%s' requested by frozen file is not supported", ARG (1))); - else - push_macro (b); - break; - - case TOKEN_VOID: - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad symbol type in m4_defn ()")); - abort (); - } -} - -/*------------------------------------------------------------------------. -| This section contains macros to handle the builtins "syscmd", "esyscmd" | -| and "sysval". "esyscmd" is GNU specific. | -`------------------------------------------------------------------------*/ - -/* Helper macros for readability. */ -#if UNIX || defined WEXITSTATUS -# define M4SYSVAL_EXITBITS(status) \ - (WIFEXITED (status) ? WEXITSTATUS (status) : 0) -# define M4SYSVAL_TERMSIGBITS(status) \ - (WIFSIGNALED (status) ? WTERMSIG (status) << 8 : 0) - -#else /* ! UNIX && ! defined WEXITSTATUS */ -/* Platforms such as mingw do not support the notion of reporting - which signal terminated a process. Furthermore if WEXITSTATUS was - not provided, then the exit value is in the low eight bits. */ -# define M4SYSVAL_EXITBITS(status) status -# define M4SYSVAL_TERMSIGBITS(status) 0 -#endif /* ! UNIX && ! defined WEXITSTATUS */ - -/* Fallback definitions if or are inadequate. */ -#ifndef WEXITSTATUS -# define WEXITSTATUS(status) (((status) >> 8) & 0xff) -#endif -#ifndef WTERMSIG -# define WTERMSIG(status) ((status) & 0x7f) -#endif -#ifndef WIFSIGNALED -# define WIFSIGNALED(status) (WTERMSIG (status) != 0) -#endif -#ifndef WIFEXITED -# define WIFEXITED(status) (WTERMSIG (status) == 0) -#endif - -/* Exit code from last "syscmd" command. */ -static int sysval; - -static void -m4_syscmd (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, 2)) - { - /* The empty command is successful. */ - sysval = 0; - return; - } - - debug_flush_files (); - sysval = system (ARG (1)); -#if FUNC_SYSTEM_BROKEN - /* OS/2 has a buggy system() that returns exit status in the lowest eight - bits, although pclose() and WEXITSTATUS are defined to return exit - status in the next eight bits. This approach can't detect signals, but - at least syscmd(`ls') still works when stdout is a terminal. An - alternate approach is popen/insert_file/pclose, but that makes stdout - a pipe, which can change how some child processes behave. */ - if (sysval != -1) - sysval <<= 8; -#endif /* FUNC_SYSTEM_BROKEN */ -} - -static void -m4_esyscmd (struct obstack *obs, int argc, token_data **argv) -{ - FILE *pin; - int ch; - - if (bad_argc (argv[0], argc, 2, 2)) - { - /* The empty command is successful. */ - sysval = 0; - return; - } - - debug_flush_files (); - errno = 0; - pin = popen (ARG (1), "r"); - if (pin == NULL) - { - M4ERROR ((warning_status, errno, - "cannot open pipe to command `%s'", ARG (1))); - sysval = -1; - } - else - { - while ((ch = getc (pin)) != EOF) - obstack_1grow (obs, (char) ch); - sysval = pclose (pin); - } -} - -static void -m4_sysval (struct obstack *obs, int argc, token_data **argv) -{ - shipout_int (obs, (sysval == -1 ? 127 - : (M4SYSVAL_EXITBITS (sysval) - | M4SYSVAL_TERMSIGBITS (sysval)))); -} - -/*-------------------------------------------------------------------------. -| This section contains the top level code for the "eval" builtin. The | -| actual work is done in the function evaluate (), which lives in eval.c. | -`-------------------------------------------------------------------------*/ - -static void -m4_eval (struct obstack *obs, int argc, token_data **argv) -{ - eval_t value = 0; - int radix = 10; - int min = 1; - const char *s; - - if (bad_argc (argv[0], argc, 2, 4)) - return; - - if (*ARG (2) && !numeric_arg (argv[0], ARG (2), &radix)) - return; - - if (radix < 1 || radix > (int) strlen (digits)) - { - M4ERROR ((warning_status, 0, - "radix in builtin `%s' out of range (radix = %d)", - ARG (0), radix)); - return; - } - - if (argc >= 4 && !numeric_arg (argv[0], ARG (3), &min)) - return; - if (min < 0) - { - M4ERROR ((warning_status, 0, - "negative width to builtin `%s'", ARG (0))); - return; - } - - if (!*ARG (1)) - M4ERROR ((warning_status, 0, - "empty string treated as 0 in builtin `%s'", ARG (0))); - else if (evaluate (ARG (1), &value)) - return; - - if (radix == 1) - { - if (value < 0) - { - obstack_1grow (obs, '-'); - value = -value; - } - /* This assumes 2's-complement for correctly handling INT_MIN. */ - while (min-- - value > 0) - obstack_1grow (obs, '0'); - while (value-- != 0) - obstack_1grow (obs, '1'); - obstack_1grow (obs, '\0'); - return; - } - - s = ntoa (value, radix); - - if (*s == '-') - { - obstack_1grow (obs, '-'); - s++; - } - for (min -= strlen (s); --min >= 0;) - obstack_1grow (obs, '0'); - - obstack_grow (obs, s, strlen (s)); -} - -static void -m4_incr (struct obstack *obs, int argc, token_data **argv) -{ - int value; - - if (bad_argc (argv[0], argc, 2, 2)) - return; - - if (!numeric_arg (argv[0], ARG (1), &value)) - return; - - shipout_int (obs, value + 1); -} - -static void -m4_decr (struct obstack *obs, int argc, token_data **argv) -{ - int value; - - if (bad_argc (argv[0], argc, 2, 2)) - return; - - if (!numeric_arg (argv[0], ARG (1), &value)) - return; - - 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. | -`-----------------------------------------------------------------------*/ - -static void -m4_divert (struct obstack *obs, int argc, token_data **argv) -{ - int i = 0; - - if (bad_argc (argv[0], argc, 1, 2)) - return; - - if (argc >= 2 && !numeric_arg (argv[0], ARG (1), &i)) - return; - - make_diversion (i); -} - -/*-----------------------------------------------------. -| Expand to the current diversion number, -1 if none. | -`-----------------------------------------------------*/ - -static void -m4_divnum (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 1)) - return; - shipout_int (obs, current_diversion); -} - -/*-----------------------------------------------------------------------. -| Bring back the diversion given by the argument list. If none is | -| specified, bring back all diversions. GNU specific is the option of | -| undiverting named files, by passing a non-numeric argument to undivert | -| (). | -`-----------------------------------------------------------------------*/ - -static void -m4_undivert (struct obstack *obs, int argc, token_data **argv) -{ - int i, file; - FILE *fp; - char *endp; - - if (argc == 1) - undivert_all (); - else - for (i = 1; i < argc; i++) - { - file = strtol (ARG (i), &endp, 10); - if (*endp == '\0' && !isspace (to_uchar (*ARG (i)))) - insert_diversion (file); - else if (no_gnu_extensions) - M4ERROR ((warning_status, 0, - "non-numeric argument to builtin `%s'", ARG (0))); - else - { - fp = m4_path_search (ARG (i), NULL); - if (fp != NULL) - { - insert_file (fp); - if (fclose (fp) == EOF) - M4ERROR ((warning_status, errno, - "error undiverting `%s'", ARG (i))); - } - else - M4ERROR ((warning_status, errno, - "cannot undivert `%s'", ARG (i))); - } - } -} - -/* This section contains various macros, which does not fall into any - specific group. These are "dnl", "shift", "changequote", "changecom" - and "changeword". */ - -/*------------------------------------------------------------------------. -| Delete all subsequent whitespace from input. The function skip_line () | -| lives in input.c. | -`------------------------------------------------------------------------*/ - -static void -m4_dnl (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 1)) - return; - - skip_line (); -} - -/*-------------------------------------------------------------------------. -| Shift all argument one to the left, discarding the first argument. Each | -| output argument is quoted with the current quotes. | -`-------------------------------------------------------------------------*/ - -static void -m4_shift (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, -1)) - return; - dump_args (obs, argc - 1, argv + 1, ",", true); -} - -/*--------------------------------------------------------------------------. -| Change the current quotes. The function set_quotes () lives in input.c. | -`--------------------------------------------------------------------------*/ - -static void -m4_changequote (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 3)) - return; - - /* Explicit NULL distinguishes between empty and missing argument. */ - set_quotes ((argc >= 2) ? TOKEN_DATA_TEXT (argv[1]) : NULL, - (argc >= 3) ? TOKEN_DATA_TEXT (argv[2]) : NULL); -} - -/*--------------------------------------------------------------------. -| Change the current comment delimiters. The function set_comment () | -| lives in input.c. | -`--------------------------------------------------------------------*/ - -static void -m4_changecom (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 3)) - return; - - /* Explicit NULL distinguishes between empty and missing argument. */ - set_comment ((argc >= 2) ? TOKEN_DATA_TEXT (argv[1]) : NULL, - (argc >= 3) ? TOKEN_DATA_TEXT (argv[2]) : NULL); -} - -#ifdef ENABLE_CHANGEWORD - -/*-----------------------------------------------------------------------. -| Change the regular expression used for breaking the input into words. | -| The function set_word_regexp () lives in input.c. | -`-----------------------------------------------------------------------*/ - -static void -m4_changeword (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, 2)) - return; - - set_word_regexp (TOKEN_DATA_TEXT (argv[1])); -} - -#endif /* ENABLE_CHANGEWORD */ - -/* 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. */ - -/*-------------------------------------------------------------------------. -| Generic include function. Include the file given by the first argument, | -| if it exists. Complain about inaccesible files iff SILENT is false. | -`-------------------------------------------------------------------------*/ - -static void -include (int argc, token_data **argv, bool silent) -{ - FILE *fp; - char *name; - - if (bad_argc (argv[0], argc, 2, 2)) - return; - - fp = m4_path_search (ARG (1), &name); - if (fp == NULL) - { - if (!silent) - M4ERROR ((warning_status, errno, - "cannot open `%s'", ARG (1))); - return; - } - - push_file (fp, name, true); - free (name); -} - -/*------------------------------------------------. -| Include a file, complaining in case of errors. | -`------------------------------------------------*/ - -static void -m4_include (struct obstack *obs, int argc, token_data **argv) -{ - include (argc, argv, false); -} - -/*----------------------------------. -| Include a file, ignoring errors. | -`----------------------------------*/ - -static void -m4_sinclude (struct obstack *obs, int argc, token_data **argv) -{ - include (argc, argv, true); -} - -/* More miscellaneous builtins -- "maketemp", "errprint", "__file__", - "__line__", and "__program__". The last three are GNU specific. */ - -/*------------------------------------------------------------------. -| Use the first argument as at template for a temporary file name. | -`------------------------------------------------------------------*/ - -/* Add trailing 'X' to NAME if necessary, securely create the file, - and place the new file name on OBS. */ -static void -mkstemp_helper (struct obstack *obs, const char *name) -{ - int fd; - int len; - int i; - - /* Guarantee that there are six trailing 'X' characters, even if the - user forgot to supply them. */ - len = strlen (name); - obstack_grow (obs, name, len); - for (i = 0; len > 0 && i < 6; i++) - if (name[--len] != 'X') - break; - for (; i < 6; i++) - obstack_1grow (obs, 'X'); - obstack_1grow (obs, '\0'); - - errno = 0; - fd = mkstemp ((char *) obstack_base (obs)); - if (fd < 0) - { - M4ERROR ((0, errno, "cannot create tempfile `%s'", name)); - obstack_free (obs, obstack_finish (obs)); - } - else - close (fd); -} - -static void -m4_maketemp (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, 2)) - return; - if (no_gnu_extensions) - { - /* 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 when we - are in traditional mode. - - 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 = ARG (1); - int len = strlen (str); - int i; - int len2; - - M4ERROR ((warning_status, 0, "recommend using mkstemp instead")); - for (i = len; i > 1; i--) - if (str[i - 1] != 'X') - break; - obstack_grow (obs, str, i); - str = ntoa ((eval_t) getpid (), 10); - len2 = strlen (str); - if (len2 > len - i) - obstack_grow0 (obs, str + len2 - (len - i), len - i); - else - { - while (i++ < len - len2) - obstack_1grow (obs, '0'); - obstack_grow0 (obs, str, len2); - } - } - else - mkstemp_helper (obs, ARG (1)); -} - -static void -m4_mkstemp (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, 2)) - return; - mkstemp_helper (obs, ARG (1)); -} - -/*----------------------------------------. -| Print all arguments on standard error. | -`----------------------------------------*/ - -static void -m4_errprint (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, -1)) - return; - dump_args (obs, argc, argv, " ", false); - obstack_1grow (obs, '\0'); - debug_flush_files (); - fprintf (stderr, "%s", (char *) obstack_finish (obs)); - fflush (stderr); -} - -static void -m4___file__ (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 1)) - return; - obstack_grow (obs, lquote.string, lquote.length); - obstack_grow (obs, current_file, strlen (current_file)); - obstack_grow (obs, rquote.string, rquote.length); -} - -static void -m4___line__ (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 1)) - return; - shipout_int (obs, current_line); -} - -static void -m4___program__ (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 1)) - return; - obstack_grow (obs, lquote.string, lquote.length); - obstack_grow (obs, program_name, strlen (program_name)); - obstack_grow (obs, rquote.string, rquote.length); -} - -/* 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. | -`-------------------------------------------------------------------------*/ - -static void -m4_m4exit (struct obstack *obs, int argc, token_data **argv) -{ - int exit_code = EXIT_SUCCESS; - - /* Warn on bad arguments, but still exit. */ - bad_argc (argv[0], argc, 1, 2); - if (argc >= 2 && !numeric_arg (argv[0], ARG (1), &exit_code)) - exit_code = EXIT_FAILURE; - if (exit_code < 0 || exit_code > 255) - { - M4ERROR ((warning_status, 0, - "exit status out of range: `%d'", exit_code)); - exit_code = EXIT_FAILURE; - } - /* Change debug stream back to stderr, to force flushing debug stream and - detect any errors it might have encountered. */ - debug_set_output (NULL); - debug_flush_files (); - if (exit_code == EXIT_SUCCESS && retcode != EXIT_SUCCESS) - exit_code = retcode; - /* Propagate non-zero status to atexit handlers. */ - if (exit_code != EXIT_SUCCESS) - exit_failure = exit_code; - 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. | -`-------------------------------------------------------------------------*/ - -static void -m4_m4wrap (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, -1)) - return; - if (no_gnu_extensions) - obstack_grow (obs, ARG (1), strlen (ARG (1))); - else - dump_args (obs, argc, argv, " ", false); - obstack_1grow (obs, '\0'); - push_wrapup ((char *) obstack_finish (obs)); -} - -/* 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. */ - -/*-----------------------------------------------------------------------. -| Set_trace () is used by "traceon" and "traceoff" to enable and disable | -| tracing of a macro. It disables tracing if DATA is NULL, otherwise it | -| enable tracing. | -`-----------------------------------------------------------------------*/ - -static void -set_trace (symbol *sym, void *data) -{ - SYMBOL_TRACED (sym) = data != NULL; - /* Remove placeholder from table if macro is undefined and untraced. */ - if (SYMBOL_TYPE (sym) == TOKEN_VOID && data == NULL) - lookup_symbol (SYMBOL_NAME (sym), SYMBOL_POPDEF); -} - -static void -m4_traceon (struct obstack *obs, int argc, token_data **argv) -{ - symbol *s; - int i; - - if (argc == 1) - hack_all_symbols (set_trace, obs); - else - for (i = 1; i < argc; i++) - { - s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_INSERT); - set_trace (s, obs); - } -} - -/*------------------------------------------------------------------------. -| Disable tracing of all specified macros, or all, if none is specified. | -`------------------------------------------------------------------------*/ - -static void -m4_traceoff (struct obstack *obs, int argc, token_data **argv) -{ - symbol *s; - int i; - - if (argc == 1) - hack_all_symbols (set_trace, NULL); - else - for (i = 1; i < argc; i++) - { - s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP); - if (s != NULL) - set_trace (s, NULL); - } -} - -/*----------------------------------------------------------------------. -| 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. | -`----------------------------------------------------------------------*/ - -static void -m4_debugmode (struct obstack *obs, int argc, token_data **argv) -{ - int new_debug_level; - int change_flag; - - if (bad_argc (argv[0], argc, 1, 2)) - return; - - if (argc == 1) - debug_level = 0; - else - { - if (ARG (1)[0] == '+' || ARG (1)[0] == '-') - { - change_flag = ARG (1)[0]; - new_debug_level = debug_decode (ARG (1) + 1); - } - else - { - change_flag = 0; - new_debug_level = debug_decode (ARG (1)); - } - - if (new_debug_level < 0) - M4ERROR ((warning_status, 0, - "Debugmode: bad debug flags: `%s'", ARG (1))); - else - { - switch (change_flag) - { - case 0: - debug_level = new_debug_level; - break; - - case '+': - debug_level |= new_debug_level; - break; - - case '-': - debug_level &= ~new_debug_level; - break; - } - } - } -} - -/*-------------------------------------------------------------------------. -| Specify the destination of the debugging output. With one argument, the | -| argument is taken as a file name, with no arguments, revert to stderr. | -`-------------------------------------------------------------------------*/ - -static void -m4_debugfile (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 1, 2)) - return; - - if (argc == 1) - debug_set_output (NULL); - else if (!debug_set_output (ARG (1))) - M4ERROR ((warning_status, errno, - "cannot set error file: `%s'", ARG (1))); -} - -/* 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. | -`---------------------------------------------*/ - -static void -m4_len (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, 2)) - return; - shipout_int (obs, strlen (ARG (1))); -} - -/*-------------------------------------------------------------------------. -| The macro expands to the first index of the second argument in the first | -| argument. | -`-------------------------------------------------------------------------*/ - -static void -m4_index (struct obstack *obs, int argc, token_data **argv) -{ - const char *haystack; - const char *result; - int retval; - - if (bad_argc (argv[0], argc, 3, 3)) - { - /* builtin(`index') is blank, but index(`abc') is 0. */ - if (argc == 2) - shipout_int (obs, 0); - return; - } - - haystack = ARG (1); - result = strstr (haystack, ARG (2)); - retval = result ? result - haystack : -1; - - 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, the | -| substring extends to the end of the first argument. | -`-------------------------------------------------------------------------*/ - -static void -m4_substr (struct obstack *obs, int argc, token_data **argv) -{ - int start = 0; - int length, avail; - - if (bad_argc (argv[0], argc, 3, 4)) - { - /* builtin(`substr') is blank, but substr(`abc') is abc. */ - if (argc == 2) - obstack_grow (obs, ARG (1), strlen (ARG (1))); - return; - } - - length = avail = strlen (ARG (1)); - if (!numeric_arg (argv[0], ARG (2), &start)) - return; - - if (argc >= 4 && !numeric_arg (argv[0], ARG (3), &length)) - return; - - if (start < 0 || length <= 0 || start >= avail) - return; - - if (start + length > avail) - length = avail - start; - obstack_grow (obs, ARG (1) + start, length); -} - -/*------------------------------------------------------------------------. -| For "translit", ranges are allowed in the second and third argument. | -| They are expanded in the following function, and the expanded strings, | -| without any ranges left, are used to translate the characters of the | -| first argument. 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. | -`------------------------------------------------------------------------*/ - -static const char * -expand_ranges (const char *s, struct obstack *obs) -{ - unsigned char from; - unsigned char to; - - for (from = '\0'; *s != '\0'; from = to_uchar (*s++)) - { - if (*s == '-' && from != '\0') - { - to = to_uchar (*++s); - if (to == '\0') - { - /* trailing dash */ - obstack_1grow (obs, '-'); - break; - } - else if (from <= to) - { - while (from++ < to) - obstack_1grow (obs, from); - } - else - { - while (--from >= to) - obstack_1grow (obs, from); - } - } - else - obstack_1grow (obs, *s); - } - obstack_1grow (obs, '\0'); - 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 (pueh). | -`----------------------------------------------------------------------*/ - -static void -m4_translit (struct obstack *obs, int argc, token_data **argv) -{ - const char *data; - const char *from; - const char *to; - char map[256] = {0}; - char found[256] = {0}; - unsigned char ch; - - if (bad_argc (argv[0], argc, 3, 4)) - { - /* builtin(`translit') is blank, but translit(`abc') is abc. */ - if (argc == 2) - obstack_grow (obs, ARG (1), strlen (ARG (1))); - return; - } - - from = ARG (2); - if (strchr (from, '-') != NULL) - { - from = expand_ranges (from, obs); - if (from == NULL) - return; - } - - to = ARG (3); - if (strchr (to, '-') != NULL) - { - to = expand_ranges (to, obs); - if (to == NULL) - return; - } - - /* Calling strchr(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. */ - for ( ; (ch = *from) != '\0'; from++) - { - if (! found[ch]) - { - found[ch] = 1; - map[ch] = *to; - } - if (*to != '\0') - to++; - } - - for (data = ARG (1); (ch = *data) != '\0'; data++) - { - if (! found[ch]) - obstack_1grow (obs, ch); - else if (map[ch]) - obstack_1grow (obs, map[ch]); - } -} - -/*----------------------------------------------------------------------. -| Frontend for printf like formatting. The function format () lives in | -| the file format.c. | -`----------------------------------------------------------------------*/ - -static void -m4_format (struct obstack *obs, int argc, token_data **argv) -{ - if (bad_argc (argv[0], argc, 2, -1)) - return; - format (obs, argc - 1, argv + 1); -} - -/*-------------------------------------------------------------------------. -| Function to perform substitution by regular expressions. Used by the | -| builtins regexp and patsubst. The changed text is placed on the | -| obstack. The substitution is REPL, with \& substituted by this part of | -| VICTIM matched by the last whole regular expression, taken from REGS[0], | -| and \N substituted by the text matched by the Nth parenthesized | -| sub-expression, taken from REGS[N]. | -`-------------------------------------------------------------------------*/ - -static int substitute_warned = 0; - -static void -substitute (struct obstack *obs, const char *victim, const char *repl, - struct re_registers *regs) -{ - int ch; - - for (;;) - { - while ((ch = *repl++) != '\\') - { - if (ch == '\0') - return; - obstack_1grow (obs, ch); - } - - switch ((ch = *repl++)) - { - case '0': - if (!substitute_warned) - { - M4ERROR ((warning_status, 0, "\ -Warning: \\0 will disappear, use \\& instead in replacements")); - substitute_warned = 1; - } - /* Fall through. */ - - case '&': - obstack_grow (obs, victim + regs->start[0], - regs->end[0] - 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 (regs->num_regs - 1 <= ch) - M4ERROR ((warning_status, 0, "\ -Warning: sub-expression %d not present", ch)); - else if (regs->end[ch] > 0) - obstack_grow (obs, victim + regs->start[ch], - regs->end[ch] - regs->start[ch]); - break; - - case '\0': - M4ERROR ((warning_status, 0, "\ -Warning: trailing \\ ignored in replacement")); - return; - - default: - obstack_1grow (obs, ch); - break; - } - } -} - -/*------------------------------------------. -| Initialize regular expression variables. | -`------------------------------------------*/ - -static void -init_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs) -{ - buf->translate = NULL; - buf->fastmap = NULL; - buf->buffer = NULL; - buf->allocated = 0; - regs->start = NULL; - regs->end = NULL; -} - -/*----------------------------------------. -| Clean up regular expression variables. | -`----------------------------------------*/ - -static void -free_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs) -{ - regfree (buf); - free (regs->start); - free (regs->end); -} - -/*--------------------------------------------------------------------------. -| 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 here is no match. Given a third argument, is changes | -| the expansion to this argument. | -`--------------------------------------------------------------------------*/ - -static void -m4_regexp (struct obstack *obs, int argc, token_data **argv) -{ - const char *victim; /* first argument */ - const char *regexp; /* regular expression */ - const char *repl; /* replacement string */ - - struct re_pattern_buffer buf; /* compiled regular expression */ - struct re_registers regs; /* for subexpression matches */ - const char *msg; /* error message from re_compile_pattern */ - int startpos; /* start position of match */ - int length; /* length of first argument */ - - if (bad_argc (argv[0], argc, 3, 4)) - { - /* builtin(`regexp') is blank, but regexp(`abc') is 0. */ - if (argc == 2) - shipout_int (obs, 0); - return; - } - - victim = TOKEN_DATA_TEXT (argv[1]); - regexp = TOKEN_DATA_TEXT (argv[2]); - - init_pattern_buffer (&buf, ®s); - msg = re_compile_pattern (regexp, strlen (regexp), &buf); - - if (msg != NULL) - { - M4ERROR ((warning_status, 0, - "bad regular expression: `%s': %s", regexp, msg)); - free_pattern_buffer (&buf, ®s); - return; - } - - length = strlen (victim); - /* Avoid overhead of allocating regs if we won't use it. */ - startpos = re_search (&buf, victim, length, 0, length, - argc == 3 ? NULL : ®s); - - if (startpos == -2) - M4ERROR ((warning_status, 0, - "error matching regular expression `%s'", regexp)); - else if (argc == 3) - shipout_int (obs, startpos); - else if (startpos >= 0) - { - repl = TOKEN_DATA_TEXT (argv[3]); - substitute (obs, victim, repl, ®s); - } - - free_pattern_buffer (&buf, ®s); -} - -/*--------------------------------------------------------------------------. -| Substitute all matches of a regexp occuring in a string. Each match of | -| the second argument (a regexp) in the first argument is changed to the | -| third argument, with \& substituted by the matched text, and \N | -| substituted by the text matched by the Nth parenthesized sub-expression. | -`--------------------------------------------------------------------------*/ - -static void -m4_patsubst (struct obstack *obs, int argc, token_data **argv) -{ - const char *victim; /* first argument */ - const char *regexp; /* regular expression */ - - struct re_pattern_buffer buf; /* compiled regular expression */ - struct re_registers regs; /* for subexpression matches */ - const char *msg; /* error message from re_compile_pattern */ - int matchpos; /* start position of match */ - int offset; /* current match offset */ - int length; /* length of first argument */ - - if (bad_argc (argv[0], argc, 3, 4)) - { - /* builtin(`patsubst') is blank, but patsubst(`abc') is abc. */ - if (argc == 2) - obstack_grow (obs, ARG (1), strlen (ARG (1))); - return; - } - - regexp = TOKEN_DATA_TEXT (argv[2]); - - init_pattern_buffer (&buf, ®s); - msg = re_compile_pattern (regexp, strlen (regexp), &buf); - - if (msg != NULL) - { - M4ERROR ((warning_status, 0, - "bad regular expression `%s': %s", regexp, msg)); - free (buf.buffer); - return; - } - - victim = TOKEN_DATA_TEXT (argv[1]); - length = strlen (victim); - - offset = 0; - matchpos = 0; - while (offset <= length) - { - matchpos = re_search (&buf, victim, length, - offset, length - offset, ®s); - 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) - M4ERROR ((warning_status, 0, - "error matching regular expression `%s'", regexp)); - else if (offset < length) - obstack_grow (obs, victim + offset, length - 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 (obs, victim, ARG (3), ®s); - - /* 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 = regs.end[0]; - if (regs.start[0] == regs.end[0]) - obstack_1grow (obs, victim[offset++]); - } - obstack_1grow (obs, '\0'); - - free_pattern_buffer (&buf, ®s); -} - -/* Finally, a placeholder builtin. This builtin is not installed by - default, but when reading back frozen files, this is associated - with any builtin we don't recognize (for example, if the frozen - file was created with a changeword capable m4, but is then loaded - by a different m4 that does not support changeword). This way, we - can keep 'm4 -R' quiet in the common case that the user did not - know or care about the builtin when the frozen file was created, - while still flagging it as a potential error if an attempt is made - to actually use the builtin. */ - -/*--------------------------------------------------------------------. -| Issue a warning that this macro is a placeholder for an unsupported | -| builtin that was requested while reloading a frozen file. | -`--------------------------------------------------------------------*/ - -void -m4_placeholder (struct obstack *obs, int argc, token_data **argv) -{ - M4ERROR ((warning_status, 0, "\ -builtin `%s' requested by frozen file is not supported", ARG (0))); -} - -/*-------------------------------------------------------------------------. -| 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. SYM points to the macro | -| definition, giving the expansion text. ARGC and ARGV are the arguments, | -| as usual. | -`-------------------------------------------------------------------------*/ - -void -expand_user_macro (struct obstack *obs, symbol *sym, - int argc, token_data **argv) -{ - const char *text; - int i; - - for (text = SYMBOL_TEXT (sym); *text != '\0';) - { - if (*text != '$') - { - obstack_1grow (obs, *text); - text++; - continue; - } - text++; - switch (*text) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (no_gnu_extensions) - { - i = *text++ - '0'; - } - else - { - for (i = 0; isdigit (to_uchar (*text)); text++) - i = i*10 + (*text - '0'); - } - if (i < argc) - obstack_grow (obs, TOKEN_DATA_TEXT (argv[i]), - strlen (TOKEN_DATA_TEXT (argv[i]))); - break; - - case '#': /* number of arguments */ - shipout_int (obs, argc - 1); - text++; - break; - - case '*': /* all arguments */ - case '@': /* ... same, but quoted */ - dump_args (obs, argc, argv, ",", *text == '@'); - text++; - break; - - default: - obstack_1grow (obs, '$'); - break; - } - } -} diff --git a/src/bin/m4/src/debug.c b/src/bin/m4/src/debug.c deleted file mode 100644 index 44354d0249..0000000000 --- a/src/bin/m4/src/debug.c +++ /dev/null @@ -1,448 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1991, 1992, 1993, 1994, 2004, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include "m4.h" - -#include -#include - -/* File for debugging output. */ -FILE *debug = NULL; - -/* Obstack for trace messages. */ -static struct obstack trace; - -extern int expansion_level; - -static void debug_set_file (FILE *); - -/*----------------------------------. -| Initialise the debugging module. | -`----------------------------------*/ - -void -debug_init (void) -{ - debug_set_file (stderr); - obstack_init (&trace); -} - -/*-----------------------------------------------------------------. -| Function to decode the debugging flags OPTS. Used by main while | -| processing option -d, and by the builtin debugmode (). | -`-----------------------------------------------------------------*/ - -int -debug_decode (const char *opts) -{ - int level; - - if (opts == NULL || *opts == '\0') - level = DEBUG_TRACE_DEFAULT; - else - { - for (level = 0; *opts; opts++) - { - switch (*opts) - { - case 'a': - level |= DEBUG_TRACE_ARGS; - break; - - case 'e': - level |= DEBUG_TRACE_EXPANSION; - break; - - case 'q': - level |= DEBUG_TRACE_QUOTE; - break; - - case 't': - level |= DEBUG_TRACE_ALL; - break; - - case 'l': - level |= DEBUG_TRACE_LINE; - break; - - case 'f': - level |= DEBUG_TRACE_FILE; - break; - - case 'p': - level |= DEBUG_TRACE_PATH; - break; - - case 'c': - level |= DEBUG_TRACE_CALL; - break; - - case 'i': - level |= DEBUG_TRACE_INPUT; - break; - - case 'x': - level |= DEBUG_TRACE_CALLID; - break; - - case 'V': - level |= DEBUG_TRACE_VERBOSE; - break; - - default: - return -1; - } - } - } - - /* This is to avoid screwing up the trace output due to changes in the - debug_level. */ - - obstack_free (&trace, obstack_finish (&trace)); - - 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. | -`------------------------------------------------------------------------*/ - -static void -debug_set_file (FILE *fp) -{ - struct stat stdout_stat, debug_stat; - - if (debug != NULL && debug != stderr && debug != stdout - && close_stream (debug) != 0) - { - M4ERROR ((warning_status, errno, "error writing to debug stream")); - retcode = EXIT_FAILURE; - } - debug = fp; - - if (debug != NULL && debug != stdout) - { - if (fstat (STDOUT_FILENO, &stdout_stat) < 0) - return; - if (fstat (fileno (debug), &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 != stderr && close_stream (debug) != 0) - { - M4ERROR ((warning_status, errno, - "error writing to debug stream")); - retcode = EXIT_FAILURE; - } - debug = stdout; - } - } -} - -/*-----------------------------------------------------------. -| Serialize files. Used before executing a system command. | -`-----------------------------------------------------------*/ - -void -debug_flush_files (void) -{ - fflush (stdout); - fflush (stderr); - if (debug != NULL && debug != stdout && debug != stderr) - fflush (debug); - /* 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 fseek() on an input file set the underlying - file pointer. 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. Mingw has bugs - when using fseek on text files, so we only strive for POSIX - behavior when we detect a UNIX environment. */ -#if UNIX - if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0 - && fflush (stdin) == 0) - { - fseek (stdin, 0, SEEK_CUR); - } -#endif /* UNIX */ -} - -/*-------------------------------------------------------------------------. -| 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. | -`-------------------------------------------------------------------------*/ - -bool -debug_set_output (const char *name) -{ - FILE *fp; - - if (name == NULL) - debug_set_file (stderr); - else if (*name == '\0') - debug_set_file (NULL); - else - { - fp = fopen (name, "a"); - if (fp == NULL) - return false; - - if (set_cloexec_flag (fileno (fp), true) != 0) - M4ERROR ((warning_status, errno, - "Warning: cannot protect debug file across forks")); - debug_set_file (fp); - } - return true; -} - -/*-----------------------------------------------------------------------. -| Print the header of a one-line debug message, starting by "m4 debug". | -`-----------------------------------------------------------------------*/ - -void -debug_message_prefix (void) -{ - fprintf (debug, "m4debug:"); - if (current_line) - { - if (debug_level & DEBUG_TRACE_FILE) - fprintf (debug, "%s:", current_file); - if (debug_level & DEBUG_TRACE_LINE) - fprintf (debug, "%d:", current_line); - } - putc (' ', debug); -} - -/* The rest 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. */ - -/*---------------------------------------------------------------------. -| Tracing output is formatted here, by a simplified printf-to-obstack | -| function trace_format (). Understands only %S, %s, %d, %l (optional | -| left quote) and %r (optional right quote). | -`---------------------------------------------------------------------*/ - -static void -trace_format (const char *fmt, ...) -{ - va_list args; - char ch; - - int d; - char nbuf[32]; - const char *s; - int slen; - int maxlen; - - va_start (args, fmt); - - while (true) - { - while ((ch = *fmt++) != '\0' && ch != '%') - obstack_1grow (&trace, ch); - - if (ch == '\0') - break; - - maxlen = 0; - switch (*fmt++) - { - case 'S': - maxlen = max_debug_argument_length; - /* fall through */ - - case 's': - s = va_arg (args, const char *); - break; - - case 'l': - s = (debug_level & DEBUG_TRACE_QUOTE) ? lquote.string : ""; - break; - - case 'r': - s = (debug_level & DEBUG_TRACE_QUOTE) ? rquote.string : ""; - break; - - case 'd': - d = va_arg (args, int); - sprintf (nbuf, "%d", d); - s = nbuf; - break; - - default: - s = ""; - break; - } - - slen = strlen (s); - if (maxlen == 0 || maxlen > slen) - obstack_grow (&trace, s, slen); - else - { - obstack_grow (&trace, s, maxlen); - obstack_grow (&trace, "...", 3); - } - } - - va_end (args); -} - -/*------------------------------------------------------------------. -| Format the standard header attached to all tracing output lines. | -`------------------------------------------------------------------*/ - -static void -trace_header (int id) -{ - trace_format ("m4trace:"); - if (current_line) - { - if (debug_level & DEBUG_TRACE_FILE) - trace_format ("%s:", current_file); - if (debug_level & DEBUG_TRACE_LINE) - trace_format ("%d:", current_line); - } - trace_format (" -%d- ", expansion_level); - if (debug_level & DEBUG_TRACE_CALLID) - trace_format ("id %d: ", id); -} - -/*----------------------------------------------------. -| Print current tracing line, and clear the obstack. | -`----------------------------------------------------*/ - -static void -trace_flush (void) -{ - char *line; - - obstack_1grow (&trace, '\0'); - line = (char *) obstack_finish (&trace); - DEBUG_PRINT1 ("%s\n", line); - obstack_free (&trace, line); -} - -/*-------------------------------------------------------------. -| Do pre-argument-collction tracing for macro NAME. Used from | -| expand_macro (). | -`-------------------------------------------------------------*/ - -void -trace_prepre (const char *name, int id) -{ - trace_header (id); - trace_format ("%s ...", name); - trace_flush (); -} - -/*-----------------------------------------------------------------------. -| Format the parts of a trace line, that can be made before the macro is | -| actually expanded. Used from expand_macro (). | -`-----------------------------------------------------------------------*/ - -void -trace_pre (const char *name, int id, int argc, token_data **argv) -{ - int i; - const builtin *bp; - - trace_header (id); - trace_format ("%s", name); - - if (argc > 1 && (debug_level & DEBUG_TRACE_ARGS)) - { - trace_format ("("); - - for (i = 1; i < argc; i++) - { - if (i != 1) - trace_format (", "); - - switch (TOKEN_DATA_TYPE (argv[i])) - { - case TOKEN_TEXT: - trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv[i])); - break; - - case TOKEN_FUNC: - bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[i])); - if (bp == NULL) - { - M4ERROR ((warning_status, 0, "\ -INTERNAL ERROR: builtin not found in builtin table! (trace_pre ())")); - abort (); - } - trace_format ("<%s>", bp->name); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad token data type (trace_pre ())")); - abort (); - } - - } - trace_format (")"); - } - - if (debug_level & DEBUG_TRACE_CALL) - { - trace_format (" -> ???"); - trace_flush (); - } -} - -/*-------------------------------------------------------------------. -| Format the final part of a trace line and print it all. Used from | -| expand_macro (). | -`-------------------------------------------------------------------*/ - -void -trace_post (const char *name, int id, int argc, token_data **argv, - const char *expanded) -{ - if (debug_level & DEBUG_TRACE_CALL) - { - trace_header (id); - trace_format ("%s%s", name, (argc > 1) ? "(...)" : ""); - } - - if (expanded && (debug_level & DEBUG_TRACE_EXPANSION)) - trace_format (" -> %l%S%r", expanded); - trace_flush (); -} diff --git a/src/bin/m4/src/eval.c b/src/bin/m4/src/eval.c deleted file mode 100644 index c2a55cbf7c..0000000000 --- a/src/bin/m4/src/eval.c +++ /dev/null @@ -1,799 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006 - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* This file contains the functions to evaluate integer expressions for - the "eval" macro. It is a little, fairly self-contained module, with - its own scanner, and a recursive descent parser. The only entry point - is evaluate (). For POSIX semantics of the "eval" macro, the type - eval_t must be a 32-bit signed integer. */ - -#include "m4.h" - -/* Evaluates token types. */ - -typedef enum eval_token - { - ERROR, - PLUS, MINUS, - EXPONENT, - TIMES, DIVIDE, MODULO, - EQ, NOTEQ, GT, GTEQ, LS, LSEQ, - LSHIFT, RSHIFT, - LNOT, LAND, LOR, - NOT, AND, OR, XOR, - LEFTP, RIGHTP, - NUMBER, EOTEXT - } -eval_token; - -/* Error types. */ - -typedef enum eval_error - { - NO_ERROR, - MISSING_RIGHT, - SYNTAX_ERROR, - UNKNOWN_INPUT, - EXCESS_INPUT, - DIVIDE_ZERO, - MODULO_ZERO - } -eval_error; - -static eval_error logical_or_term (eval_token, eval_t *); -static eval_error logical_and_term (eval_token, eval_t *); -static eval_error or_term (eval_token, eval_t *); -static eval_error xor_term (eval_token, eval_t *); -static eval_error and_term (eval_token, eval_t *); -static eval_error not_term (eval_token, eval_t *); -static eval_error logical_not_term (eval_token, eval_t *); -static eval_error cmp_term (eval_token, eval_t *); -static eval_error shift_term (eval_token, eval_t *); -static eval_error add_term (eval_token, eval_t *); -static eval_error mult_term (eval_token, eval_t *); -static eval_error exp_term (eval_token, eval_t *); -static eval_error unary_term (eval_token, eval_t *); -static eval_error simple_term (eval_token, eval_t *); - -/*--------------------. -| 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; - -static void -eval_init_lex (const char *text) -{ - eval_text = text; - last_text = NULL; -} - -static void -eval_undo (void) -{ - eval_text = last_text; -} - -/* VAL is numerical value, if any. */ - -static eval_token -eval_lex (eval_t *val) -{ - while (isspace (to_uchar (*eval_text))) - eval_text++; - - last_text = eval_text; - - if (*eval_text == '\0') - 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; - - (*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) - (*val)++; - else if (digit == 0 && !*val) - continue; - else - break; - } - else if (digit >= base) - break; - else - (*val) = (*val) * base + digit; - } - return NUMBER; - } - - switch (*eval_text++) - { - case '+': - return PLUS; - case '-': - return MINUS; - case '*': - if (*eval_text == '*') - { - eval_text++; - return EXPONENT; - } - else - return TIMES; - case '/': - return DIVIDE; - case '%': - return MODULO; - case '=': - if (*eval_text == '=') - eval_text++; - return EQ; - case '!': - if (*eval_text == '=') - { - eval_text++; - return NOTEQ; - } - else - return LNOT; - case '>': - if (*eval_text == '=') - { - eval_text++; - return GTEQ; - } - else if (*eval_text == '>') - { - eval_text++; - return RSHIFT; - } - else - return GT; - case '<': - if (*eval_text == '=') - { - eval_text++; - return LSEQ; - } - else if (*eval_text == '<') - { - eval_text++; - return LSHIFT; - } - else - return LS; - case '^': - return XOR; - case '~': - return NOT; - case '&': - if (*eval_text == '&') - { - eval_text++; - return LAND; - } - else - return AND; - case '|': - if (*eval_text == '|') - { - eval_text++; - return LOR; - } - else - return OR; - case '(': - return LEFTP; - case ')': - return RIGHTP; - default: - return ERROR; - } -} - -/*---------------------------------------. -| Main entry point, called from "eval". | -`---------------------------------------*/ - -bool -evaluate (const char *expr, eval_t *val) -{ - eval_token et; - eval_error err; - - eval_init_lex (expr); - et = eval_lex (val); - err = logical_or_term (et, val); - - if (err == NO_ERROR && *eval_text != '\0') - err = EXCESS_INPUT; - - switch (err) - { - case NO_ERROR: - break; - - case MISSING_RIGHT: - M4ERROR ((warning_status, 0, - "bad expression in eval (missing right parenthesis): %s", - expr)); - break; - - case SYNTAX_ERROR: - M4ERROR ((warning_status, 0, - "bad expression in eval: %s", expr)); - break; - - case UNKNOWN_INPUT: - M4ERROR ((warning_status, 0, - "bad expression in eval (bad input): %s", expr)); - break; - - case EXCESS_INPUT: - M4ERROR ((warning_status, 0, - "bad expression in eval (excess input): %s", expr)); - break; - - case DIVIDE_ZERO: - M4ERROR ((warning_status, 0, - "divide by zero in eval: %s", expr)); - break; - - case MODULO_ZERO: - M4ERROR ((warning_status, 0, - "modulo by zero in eval: %s", expr)); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad error code in evaluate ()")); - abort (); - } - - return err != NO_ERROR; -} - -/*---------------------------. -| Recursive descent parser. | -`---------------------------*/ - -static eval_error -logical_or_term (eval_token et, eval_t *v1) -{ - eval_t v2; - eval_error er; - - if ((er = logical_and_term (et, v1)) != NO_ERROR) - return er; - - while ((et = eval_lex (&v2)) == LOR) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = logical_and_term (et, &v2)) != NO_ERROR) - return er; - - *v1 = *v1 || v2; - } - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -logical_and_term (eval_token et, eval_t *v1) -{ - eval_t v2; - eval_error er; - - if ((er = or_term (et, v1)) != NO_ERROR) - return er; - - while ((et = eval_lex (&v2)) == LAND) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = or_term (et, &v2)) != NO_ERROR) - return er; - - *v1 = *v1 && v2; - } - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -or_term (eval_token et, eval_t *v1) -{ - eval_t v2; - eval_error er; - - if ((er = xor_term (et, v1)) != NO_ERROR) - return er; - - while ((et = eval_lex (&v2)) == OR) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = xor_term (et, &v2)) != NO_ERROR) - return er; - - *v1 = *v1 | v2; - } - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -xor_term (eval_token et, eval_t *v1) -{ - eval_t v2; - eval_error er; - - if ((er = and_term (et, v1)) != NO_ERROR) - return er; - - while ((et = eval_lex (&v2)) == XOR) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = and_term (et, &v2)) != NO_ERROR) - return er; - - *v1 = *v1 ^ v2; - } - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -and_term (eval_token et, eval_t *v1) -{ - eval_t v2; - eval_error er; - - if ((er = not_term (et, v1)) != NO_ERROR) - return er; - - while ((et = eval_lex (&v2)) == AND) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = not_term (et, &v2)) != NO_ERROR) - return er; - - *v1 = *v1 & v2; - } - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -not_term (eval_token et, eval_t *v1) -{ - eval_error er; - - if (et == NOT) - { - et = eval_lex (v1); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = not_term (et, v1)) != NO_ERROR) - return er; - *v1 = ~*v1; - } - else - if ((er = logical_not_term (et, v1)) != NO_ERROR) - return er; - - return NO_ERROR; -} - -static eval_error -logical_not_term (eval_token et, eval_t *v1) -{ - eval_error er; - - if (et == LNOT) - { - et = eval_lex (v1); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = logical_not_term (et, v1)) != NO_ERROR) - return er; - *v1 = !*v1; - } - else - if ((er = cmp_term (et, v1)) != NO_ERROR) - return er; - - return NO_ERROR; -} - -static eval_error -cmp_term (eval_token et, eval_t *v1) -{ - eval_token op; - eval_t v2; - eval_error er; - - if ((er = shift_term (et, v1)) != NO_ERROR) - return er; - - while ((op = eval_lex (&v2)) == EQ || op == NOTEQ - || op == GT || op == GTEQ - || op == LS || op == LSEQ) - { - - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = shift_term (et, &v2)) != NO_ERROR) - return er; - - switch (op) - { - case EQ: - *v1 = *v1 == v2; - break; - - case NOTEQ: - *v1 = *v1 != v2; - break; - - case GT: - *v1 = *v1 > v2; - break; - - case GTEQ: - *v1 = *v1 >= v2; - break; - - case LS: - *v1 = *v1 < v2; - break; - - case LSEQ: - *v1 = *v1 <= v2; - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad comparison operator in cmp_term ()")); - abort (); - } - } - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -shift_term (eval_token et, eval_t *v1) -{ - eval_token op; - eval_t v2; - eval_error er; - - if ((er = add_term (et, v1)) != NO_ERROR) - return er; - - while ((op = eval_lex (&v2)) == LSHIFT || op == RSHIFT) - { - - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = add_term (et, &v2)) != NO_ERROR) - return er; - - /* Shifting by a negative number, or by greater than the width, is - undefined in C, but POSIX requires eval to operate on 32-bit signed - numbers. Explicitly mask the right argument to ensure defined - behavior. */ - switch (op) - { - case LSHIFT: - *v1 = *v1 << (v2 & 0x1f); - break; - - case RSHIFT: - /* This assumes 2's-complement with sign-extension, since shifting - a negative number right is implementation-defined in C. */ - *v1 = *v1 >> (v2 & 0x1f); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad shift operator in shift_term ()")); - abort (); - } - } - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -add_term (eval_token et, eval_t *v1) -{ - eval_token op; - eval_t v2; - eval_error er; - - if ((er = mult_term (et, v1)) != NO_ERROR) - return er; - - while ((op = eval_lex (&v2)) == PLUS || op == MINUS) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = mult_term (et, &v2)) != NO_ERROR) - return er; - - if (op == PLUS) - *v1 = *v1 + v2; - else - *v1 = *v1 - v2; - } - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -mult_term (eval_token et, eval_t *v1) -{ - eval_token op; - eval_t v2; - eval_error er; - - if ((er = exp_term (et, v1)) != NO_ERROR) - return er; - - while ((op = eval_lex (&v2)) == TIMES || op == DIVIDE || op == MODULO) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = exp_term (et, &v2)) != NO_ERROR) - return er; - - switch (op) - { - case TIMES: - *v1 = *v1 * v2; - break; - - case DIVIDE: - if (v2 == 0) - return DIVIDE_ZERO; - else if (v2 == -1) - /* Avoid the x86 SIGFPE on INT_MIN / -1. */ - *v1 = -*v1; - else - *v1 = *v1 / v2; - break; - - case MODULO: - if (v2 == 0) - return MODULO_ZERO; - else if (v2 == -1) - /* Avoid the x86 SIGFPE on INT_MIN % -1. */ - *v1 = 0; - else - *v1 = *v1 % v2; - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad operator in mult_term ()")); - abort (); - } - } - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -exp_term (eval_token et, eval_t *v1) -{ - register eval_t result; - eval_t v2; - eval_error er; - - if ((er = unary_term (et, v1)) != NO_ERROR) - return er; - result = *v1; - - while ((et = eval_lex (&v2)) == EXPONENT) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = exp_term (et, &v2)) != NO_ERROR) - return er; - - result = 1; - while (v2-- > 0) - result *= *v1; - *v1 = result; - } - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -unary_term (eval_token et, eval_t *v1) -{ - eval_token et2 = et; - eval_error er; - - if (et == PLUS || et == MINUS) - { - et2 = eval_lex (v1); - if (et2 == ERROR) - return UNKNOWN_INPUT; - - if ((er = simple_term (et2, v1)) != NO_ERROR) - return er; - - if (et == MINUS) - *v1 = -*v1; - } - else - if ((er = simple_term (et, v1)) != NO_ERROR) - return er; - - return NO_ERROR; -} - -static eval_error -simple_term (eval_token et, eval_t *v1) -{ - eval_t v2; - eval_error er; - - switch (et) - { - case LEFTP: - et = eval_lex (v1); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = logical_or_term (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; - - default: - return SYNTAX_ERROR; - } - return NO_ERROR; -} diff --git a/src/bin/m4/src/format.c b/src/bin/m4/src/format.c deleted file mode 100644 index 2482041521..0000000000 --- a/src/bin/m4/src/format.c +++ /dev/null @@ -1,298 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006 - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* printf like formatting for m4. */ - -#include "m4.h" -#include "xvasprintf.h" - -/* Simple varargs substitute. */ - -#define ARG_INT(argc, argv) \ - ((argc == 0) ? 0 : \ - (--argc, argv++, atoi (TOKEN_DATA_TEXT (argv[-1])))) - -#define ARG_UINT(argc, argv) \ - ((argc == 0) ? 0 : \ - (--argc, argv++, (unsigned int) atoi (TOKEN_DATA_TEXT (argv[-1])))) - -#define ARG_LONG(argc, argv) \ - ((argc == 0) ? 0 : \ - (--argc, argv++, atol (TOKEN_DATA_TEXT (argv[-1])))) - -#define ARG_ULONG(argc, argv) \ - ((argc == 0) ? 0 : \ - (--argc, argv++, (unsigned long) atol (TOKEN_DATA_TEXT (argv[-1])))) - -#define ARG_STR(argc, argv) \ - ((argc == 0) ? "" : \ - (--argc, argv++, TOKEN_DATA_TEXT (argv[-1]))) - -#define ARG_DOUBLE(argc, argv) \ - ((argc == 0) ? 0 : \ - (--argc, argv++, atof (TOKEN_DATA_TEXT (argv[-1])))) - - -/*------------------------------------------------------------------------. -| 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. | -`------------------------------------------------------------------------*/ - -void -format (struct obstack *obs, int argc, token_data **argv) -{ - char *fmt; /* format control string */ - const char *fstart; /* beginning of current format spec */ - int c; /* a simple character */ - - /* Flags. */ - char flags; /* 1 iff treating flags */ - - /* Precision specifiers. */ - int width; /* minimum field width */ - int prec; /* precision */ - char lflag; /* long flag */ - char hflag; /* short flag */ - - /* Buffer and stuff. */ - char *str; /* malloc'd buffer of formatted text */ - enum {INT, UINT, LONG, ULONG, DOUBLE, STR} datatype; - - fmt = (char *) ARG_STR (argc, argv); - for (;;) - { - while ((c = *fmt++) != '%') - { - if (c == 0) - return; - obstack_1grow (obs, c); - } - - fstart = fmt - 1; - - if (*fmt == '%') - { - obstack_1grow (obs, '%'); - fmt++; - continue; - } - - /* Parse flags. */ - flags = 1; - do - { - switch (*fmt) - { - case '-': /* left justification */ - case '+': /* mandatory sign */ - case ' ': /* space instead of positive sign */ - case '0': /* zero padding */ - case '#': /* alternate output */ - break; - - default: - flags = 0; - break; - } - } - while (flags && fmt++); - - /* Minimum field width. */ - width = -1; - if (*fmt == '*') - { - width = ARG_INT (argc, argv); - fmt++; - } - else if (isdigit (to_uchar (*fmt))) - { - do - { - fmt++; - } - while (isdigit (to_uchar (*fmt))); - } - - /* Maximum precision. */ - prec = -1; - if (*fmt == '.') - { - if (*(++fmt) == '*') - { - prec = ARG_INT (argc, argv); - ++fmt; - } - else if (isdigit (to_uchar (*fmt))) - { - do - { - fmt++; - } - while (isdigit (to_uchar (*fmt))); - } - } - - /* Length modifiers. */ - lflag = (*fmt == 'l'); - hflag = (*fmt == 'h'); - if (lflag || hflag) - fmt++; - - switch (*fmt++) - { - - case '\0': - return; - - case 'c': - datatype = INT; - break; - - case 's': - datatype = STR; - break; - - case 'd': - case 'i': - if (lflag) - { - datatype = LONG; - } - else - { - datatype = INT; - } - break; - - case 'o': - case 'x': - case 'X': - case 'u': - if (lflag) - { - datatype = ULONG; - } - else - { - datatype = UINT; - } - break; - - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - datatype = DOUBLE; - break; - - default: - continue; - } - - c = *fmt; - *fmt = '\0'; - - switch(datatype) - { - case INT: - if (width != -1 && prec != -1) - str = xasprintf (fstart, width, prec, ARG_INT(argc, argv)); - else if (width != -1) - str = xasprintf (fstart, width, ARG_INT(argc, argv)); - else if (prec != -1) - str = xasprintf (fstart, prec, ARG_INT(argc, argv)); - else - str = xasprintf (fstart, ARG_INT(argc, argv)); - break; - - case UINT: - if (width != -1 && prec != -1) - str = xasprintf (fstart, width, prec, ARG_UINT(argc, argv)); - else if (width != -1) - str = xasprintf (fstart, width, ARG_UINT(argc, argv)); - else if (prec != -1) - str = xasprintf (fstart, prec, ARG_UINT(argc, argv)); - else - str = xasprintf (fstart, ARG_UINT(argc, argv)); - break; - - case LONG: - if (width != -1 && prec != -1) - str = xasprintf (fstart, width, prec, ARG_LONG(argc, argv)); - else if (width != -1) - str = xasprintf (fstart, width, ARG_LONG(argc, argv)); - else if (prec != -1) - str = xasprintf (fstart, prec, ARG_LONG(argc, argv)); - else - str = xasprintf (fstart, ARG_LONG(argc, argv)); - break; - - case ULONG: - if (width != -1 && prec != -1) - str = xasprintf (fstart, width, prec, ARG_ULONG(argc, argv)); - else if (width != -1) - str = xasprintf (fstart, width, ARG_ULONG(argc, argv)); - else if (prec != -1) - str = xasprintf (fstart, prec, ARG_ULONG(argc, argv)); - else - str = xasprintf (fstart, ARG_ULONG(argc, argv)); - break; - - case DOUBLE: - if (width != -1 && prec != -1) - str = xasprintf (fstart, width, prec, ARG_DOUBLE(argc, argv)); - else if (width != -1) - str = xasprintf (fstart, width, ARG_DOUBLE(argc, argv)); - else if (prec != -1) - str = xasprintf (fstart, prec, ARG_DOUBLE(argc, argv)); - else - str = xasprintf (fstart, ARG_DOUBLE(argc, argv)); - break; - - case STR: - if (width != -1 && prec != -1) - str = xasprintf (fstart, width, prec, ARG_STR(argc, argv)); - else if (width != -1) - str = xasprintf (fstart, width, ARG_STR(argc, argv)); - else if (prec != -1) - str = xasprintf (fstart, prec, ARG_STR(argc, argv)); - else - str = xasprintf (fstart, ARG_STR(argc, argv)); - break; - - default: - abort(); - } - - *fmt = c; - - /* NULL was returned on failure, such as invalid format string. For - now, just silently ignore that bad specifier. */ - if (str == NULL) - continue; - - obstack_grow (obs, str, strlen (str)); - free (str); - } -} diff --git a/src/bin/m4/src/freeze.c b/src/bin/m4/src/freeze.c deleted file mode 100644 index 7b8a7bc30c..0000000000 --- a/src/bin/m4/src/freeze.c +++ /dev/null @@ -1,379 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006 - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* This module handles frozen files. */ - -#include "m4.h" - -/*-------------------------------------------------------------------. -| Destructively reverse a symbol list and return the reversed list. | -`-------------------------------------------------------------------*/ - -static symbol * -reverse_symbol_list (symbol *sym) -{ - symbol *result; - symbol *next; - - result = NULL; - while (sym) - { - next = SYMBOL_NEXT (sym); - SYMBOL_NEXT (sym) = result; - result = sym; - sym = next; - } - return result; -} - -/*------------------------------------------------. -| Produce a frozen state to the given file NAME. | -`------------------------------------------------*/ - -void -produce_frozen_state (const char *name) -{ - FILE *file; - int h; - symbol *sym; - const builtin *bp; - - if (file = fopen (name, O_BINARY ? "wb" : "w"), !file) - { - M4ERROR ((warning_status, errno, name)); - return; - } - - /* Write a recognizable header. */ - - fprintf (file, "# This is a frozen state file generated by %s\n", - PACKAGE_STRING); - fprintf (file, "V1\n"); - - /* Dump quote delimiters. */ - - if (strcmp (lquote.string, DEF_LQUOTE) || strcmp (rquote.string, DEF_RQUOTE)) - { - fprintf (file, "Q%d,%d\n", (int) lquote.length, (int) rquote.length); - fputs (lquote.string, file); - fputs (rquote.string, file); - fputc ('\n', file); - } - - /* Dump comment delimiters. */ - - if (strcmp (bcomm.string, DEF_BCOMM) || strcmp (ecomm.string, DEF_ECOMM)) - { - fprintf (file, "C%d,%d\n", (int) bcomm.length, (int) ecomm.length); - fputs (bcomm.string, file); - fputs (ecomm.string, file); - fputc ('\n', file); - } - - /* Dump all symbols. */ - - for (h = 0; h < hash_table_size; h++) - { - - /* 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. */ - - symtab[h] = reverse_symbol_list (symtab[h]); - for (sym = symtab[h]; sym; sym = SYMBOL_NEXT (sym)) - { - switch (SYMBOL_TYPE (sym)) - { - case TOKEN_TEXT: - fprintf (file, "T%d,%d\n", - (int) strlen (SYMBOL_NAME (sym)), - (int) strlen (SYMBOL_TEXT (sym))); - fputs (SYMBOL_NAME (sym), file); - fputs (SYMBOL_TEXT (sym), file); - fputc ('\n', file); - break; - - case TOKEN_FUNC: - bp = find_builtin_by_addr (SYMBOL_FUNC (sym)); - if (bp == NULL) - { - M4ERROR ((warning_status, 0, "\ -INTERNAL ERROR: builtin not found in builtin table!")); - abort (); - } - fprintf (file, "F%d,%d\n", - (int) strlen (SYMBOL_NAME (sym)), - (int) strlen (bp->name)); - fputs (SYMBOL_NAME (sym), file); - fputs (bp->name, file); - fputc ('\n', file); - break; - - default: - M4ERROR ((warning_status, 0, "\ -INTERNAL ERROR: bad token data type in freeze_one_symbol ()")); - abort (); - break; - } - } - - /* Reverse the bucket once more, putting it back as it was. */ - - symtab[h] = reverse_symbol_list (symtab[h]); - } - - /* Let diversions be issued from output.c module, its cleaner to have this - piece of code there. */ - - freeze_diversions (file); - - /* All done. */ - - fputs ("# End of frozen state file\n", file); - if (close_stream (file) != 0) - M4ERROR ((EXIT_FAILURE, errno, "unable to create frozen state")); -} - -/*----------------------------------------------------------------------. -| Issue a message saying that some character is an EXPECTED character. | -`----------------------------------------------------------------------*/ - -static void -issue_expect_message (int expected) -{ - if (expected == '\n') - M4ERROR ((EXIT_FAILURE, 0, "expecting line feed in frozen file")); - else - M4ERROR ((EXIT_FAILURE, 0, "expecting character `%c' in frozen file", - expected)); -} - -/*-------------------------------------------------. -| Reload a frozen state from the given file NAME. | -`-------------------------------------------------*/ - -/* We are seeking speed, here. */ - -void -reload_frozen_state (const char *name) -{ - FILE *file; - int character; - int operation; - char *string[2]; - int allocated[2]; - int number[2]; - const builtin *bp; - -#define GET_CHARACTER \ - (character = getc (file)) - -#define GET_NUMBER(Number) \ - do \ - { \ - (Number) = 0; \ - while (isdigit (character)) \ - { \ - (Number) = 10 * (Number) + character - '0'; \ - GET_CHARACTER; \ - } \ - } \ - while (0) - -#define VALIDATE(Expected) \ - do \ - { \ - if (character != (Expected)) \ - issue_expect_message ((Expected)); \ - } \ - while (0) - - /* Skip comments (`#' at beginning of line) and blank lines, setting - character to the next directive or to EOF. */ - -#define GET_DIRECTIVE \ - do \ - { \ - GET_CHARACTER; \ - if (character == '#') \ - { \ - while (character != EOF && character != '\n') \ - GET_CHARACTER; \ - VALIDATE ('\n'); \ - } \ - } \ - while (character == '\n') - - file = m4_path_search (name, NULL); - if (file == NULL) - M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name)); - - allocated[0] = 100; - string[0] = xcharalloc ((size_t) allocated[0]); - allocated[1] = 100; - string[1] = xcharalloc ((size_t) allocated[1]); - - /* Validate format version. Only `1' is acceptable for now. */ - GET_DIRECTIVE; - VALIDATE ('V'); - GET_CHARACTER; - GET_NUMBER (number[0]); - if (number[0] > 1) - M4ERROR ((EXIT_MISMATCH, 0, - "frozen file version %d greater than max supported of 1", - number[0])); - else if (number[0] < 1) - M4ERROR ((EXIT_FAILURE, 0, - "ill-formed frozen file, version directive expected")); - VALIDATE ('\n'); - - GET_DIRECTIVE; - while (character != EOF) - { - switch (character) - { - default: - M4ERROR ((EXIT_FAILURE, 0, "ill-formed frozen file")); - - case 'C': - case 'D': - case 'F': - case 'T': - case 'Q': - operation = character; - GET_CHARACTER; - - /* Get string lengths. Accept a negative diversion number. */ - - if (operation == 'D' && character == '-') - { - GET_CHARACTER; - GET_NUMBER (number[0]); - number[0] = -number[0]; - } - else - GET_NUMBER (number[0]); - VALIDATE (','); - GET_CHARACTER; - GET_NUMBER (number[1]); - VALIDATE ('\n'); - - if (operation != 'D') - { - - /* Get first string contents. */ - - if (number[0] + 1 > allocated[0]) - { - free (string[0]); - allocated[0] = number[0] + 1; - string[0] = xcharalloc ((size_t) allocated[0]); - } - - if (number[0] > 0) - if (!fread (string[0], (size_t) number[0], 1, file)) - M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file")); - - string[0][number[0]] = '\0'; - } - - /* Get second string contents. */ - - if (number[1] + 1 > allocated[1]) - { - free (string[1]); - allocated[1] = number[1] + 1; - string[1] = xcharalloc ((size_t) allocated[1]); - } - - if (number[1] > 0) - if (!fread (string[1], (size_t) number[1], 1, file)) - M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file")); - - string[1][number[1]] = '\0'; - GET_CHARACTER; - VALIDATE ('\n'); - - /* Act according to operation letter. */ - - switch (operation) - { - case 'C': - - /* Change comment strings. */ - - set_comment (string[0], string[1]); - break; - - case 'D': - - /* Select a diversion and add a string to it. */ - - make_diversion (number[0]); - if (number[1] > 0) - shipout_text (NULL, string[1], number[1]); - break; - - case 'F': - - /* Enter a macro having a builtin function as a definition. */ - - bp = find_builtin_by_name (string[1]); - define_builtin (string[0], bp, SYMBOL_PUSHDEF); - break; - - case 'T': - - /* Enter a macro having an expansion text as a definition. */ - - define_user_macro (string[0], string[1], SYMBOL_PUSHDEF); - break; - - case 'Q': - - /* Change quote strings. */ - - set_quotes (string[0], string[1]); - break; - - default: - - /* Cannot happen. */ - - break; - } - break; - - } - GET_DIRECTIVE; - } - - free (string[0]); - free (string[1]); - errno = 0; - if (ferror (file) || fclose (file) != 0) - M4ERROR ((EXIT_FAILURE, errno, "unable to read frozen state")); - -#undef GET_CHARACTER -#undef GET_DIRECTIVE -#undef GET_NUMBER -#undef VALIDATE -} diff --git a/src/bin/m4/src/input.c b/src/bin/m4/src/input.c deleted file mode 100644 index 6296281bf6..0000000000 --- a/src/bin/m4/src/input.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006 - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* Handling of different input sources, and lexical analysis. */ - -#include "m4.h" - -/* Unread input can be either files, that should be read (eg. included - files), strings, which should be rescanned (eg. macro expansion text), - or quoted macro definitions (as returned by the builtin "defn"). - Unread input are organised in a stack, implemented with an obstack. - Each input source is described by a "struct input_block". The obstack - is "current_input". The top of the input stack is "isp". - - 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. - - Pushing new input on the input stack is done by push_file (), - push_string (), push_wrapup () (for wrapup text), and push_macro () - (for macro definitions). Because macro expansion needs direct access - to the current input obstack (for optimisation), push_string () are - split in two functions, push_string_init (), which returns a pointer - to the current input stack, and push_string_finish (), which return a - pointer to the final text. The input_block *next is used to manage - the coordination between the different push routines. - - The current file and line number are stored in two global - variables, for use by the error handling functions in m4.c. Macro - expansion wants to report the line where a macro name was detected, - rather than where it finished collecting arguments. This also - applies to text resulting from macro expansions. So each input - block maintains its own notion of the current file and line, and - swapping between input blocks updates the global variables - accordingly. */ - -#ifdef ENABLE_CHANGEWORD -#include "regex.h" -#endif - -enum input_type -{ - INPUT_STRING, /* String resulting from macro expansion. */ - INPUT_FILE, /* File from command line or include. */ - INPUT_MACRO /* Builtin resulting from defn. */ -}; - -typedef enum input_type input_type; - -struct input_block -{ - struct input_block *prev; /* previous input_block on the input stack */ - input_type type; /* see enum values */ - const char *file; /* file where this input is from */ - int line; /* line where this input is from */ - union - { - struct - { - char *string; /* remaining string value */ - } - u_s; /* INPUT_STRING */ - struct - { - FILE *fp; /* input file handle */ - bool end : 1; /* true if peek has seen EOF */ - bool close : 1; /* true if we should close file on pop */ - bool advance_line : 1; /* track previous start_of_input_line */ - } - u_f; /* INPUT_FILE */ - builtin_func *func; /* pointer to macro's function */ - } - u; -}; - -typedef struct input_block input_block; - - -/* Current input file name. */ -const char *current_file; - -/* Current input line number. */ -int current_line; - -/* Obstack for storing individual tokens. */ -static struct obstack token_stack; - -/* Obstack for storing file names. */ -static struct obstack file_names; - -/* Wrapup input stack. */ -static struct obstack *wrapup_stack; - -/* Current stack, from input or wrapup. */ -static struct obstack *current_input; - -/* Bottom of token_stack, for obstack_free. */ -static void *token_bottom; - -/* Pointer to top of current_input. */ -static input_block *isp; - -/* Pointer to top of wrapup_stack. */ -static input_block *wsp; - -/* Aux. for handling split push_string (). */ -static 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; - -#define CHAR_EOF 256 /* character return on EOF */ -#define CHAR_MACRO 257 /* character return for MACRO token */ - -/* Quote chars. */ -STRING rquote; -STRING lquote; - -/* Comment chars. */ -STRING bcomm; -STRING ecomm; - -#ifdef ENABLE_CHANGEWORD - -# define DEFAULT_WORD_REGEXP "[_a-zA-Z][_a-zA-Z0-9]*" - -static char *word_start; -static struct re_pattern_buffer word_regexp; -static int default_word_regexp; -static struct re_registers regs; - -#else /* ! ENABLE_CHANGEWORD */ -# define default_word_regexp 1 -#endif /* ! ENABLE_CHANGEWORD */ - -#ifdef DEBUG_INPUT -static const char *token_type_string (token_type); -#endif - - -/*-------------------------------------------------------------------. -| push_file () pushes an input file on the input stack, saving the | -| current file name and line number. If next is non-NULL, this push | -| invalidates a call to push_string_init (), whose storage is | -| consequently released. If CLOSE, then close FP after EOF is | -| detected. | -`-------------------------------------------------------------------*/ - -void -push_file (FILE *fp, const char *title, bool close) -{ - input_block *i; - - if (next != NULL) - { - obstack_free (current_input, next); - next = NULL; - } - - if (debug_level & DEBUG_TRACE_INPUT) - DEBUG_MESSAGE1 ("input read from %s", title); - - i = (input_block *) obstack_alloc (current_input, - sizeof (struct input_block)); - i->type = INPUT_FILE; - i->file = (char *) obstack_copy0 (&file_names, title, strlen (title)); - i->line = 1; - input_change = true; - - i->u.u_f.fp = fp; - i->u.u_f.end = false; - i->u.u_f.close = close; - i->u.u_f.advance_line = start_of_input_line; - output_current_line = -1; - - i->prev = isp; - isp = i; -} - -/*---------------------------------------------------------------. -| push_macro () pushes a builtin macro's definition on the input | -| stack. If next is non-NULL, this push invalidates a call to | -| push_string_init (), whose storage is consequently released. | -`---------------------------------------------------------------*/ - -void -push_macro (builtin_func *func) -{ - input_block *i; - - if (next != NULL) - { - obstack_free (current_input, next); - next = NULL; - } - - i = (input_block *) obstack_alloc (current_input, - sizeof (struct input_block)); - i->type = INPUT_MACRO; - i->file = current_file; - i->line = current_line; - input_change = true; - - i->u.func = func; - i->prev = isp; - isp = i; -} - -/*------------------------------------------------------------------. -| First half of push_string (). The pointer next points to the new | -| input_block. | -`------------------------------------------------------------------*/ - -struct obstack * -push_string_init (void) -{ - if (next != NULL) - { - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: recursive push_string!")); - abort (); - } - - next = (input_block *) obstack_alloc (current_input, - sizeof (struct input_block)); - next->type = INPUT_STRING; - next->file = current_file; - next->line = current_line; - - return current_input; -} - -/*------------------------------------------------------------------------. -| Last half of push_string (). If next is now NULL, a call to push_file | -| () has invalidated the previous call to push_string_init (), so we just | -| give up. If the new object is void, we do not push it. The function | -| push_string_finish () returns a pointer to the finished object. This | -| pointer is only for temporary use, since reading the next token might | -| release the memory used for the object. | -`------------------------------------------------------------------------*/ - -const char * -push_string_finish (void) -{ - const char *ret = NULL; - - if (next == NULL) - return NULL; - - if (obstack_object_size (current_input) > 0) - { - obstack_1grow (current_input, '\0'); - next->u.u_s.string = (char *) obstack_finish (current_input); - next->prev = isp; - isp = next; - ret = isp->u.u_s.string; /* for immediate use only */ - input_change = true; - } - else - obstack_free (current_input, next); /* people might leave garbage on it. */ - next = NULL; - return ret; -} - -/*------------------------------------------------------------------. -| The function push_wrapup () pushes a string on the wrapup stack. | -| When the normal input stack gets empty, the wrapup stack will | -| become the input stack, and push_string () and push_file () will | -| operate on wrapup_stack. Push_wrapup should be done as | -| push_string (), but this will suffice, as long as arguments to | -| m4_m4wrap () are moderate in size. | -`------------------------------------------------------------------*/ - -void -push_wrapup (const char *s) -{ - input_block *i; - i = (input_block *) obstack_alloc (wrapup_stack, - sizeof (struct input_block)); - i->prev = wsp; - i->type = INPUT_STRING; - i->file = current_file; - i->line = current_line; - i->u.u_s.string = (char *) obstack_copy0 (wrapup_stack, s, strlen (s)); - wsp = i; -} - - -/*-------------------------------------------------------------------------. -| The function pop_input () pops one level of input sources. If the | -| popped input_block is a file, current_file and current_line are reset to | -| the saved values before the memory for the input_block are released. | -`-------------------------------------------------------------------------*/ - -static void -pop_input (void) -{ - input_block *tmp = isp->prev; - - switch (isp->type) - { - case INPUT_STRING: - case INPUT_MACRO: - break; - - case INPUT_FILE: - if (debug_level & DEBUG_TRACE_INPUT) - { - if (tmp) - DEBUG_MESSAGE2 ("input reverted to %s, line %d", - tmp->file, tmp->line); - else - DEBUG_MESSAGE ("input exhausted"); - } - - if (ferror (isp->u.u_f.fp)) - { - M4ERROR ((warning_status, 0, "read error")); - if (isp->u.u_f.close) - fclose (isp->u.u_f.fp); - retcode = EXIT_FAILURE; - } - else if (isp->u.u_f.close && fclose (isp->u.u_f.fp) == EOF) - { - M4ERROR ((warning_status, errno, "error reading file")); - retcode = EXIT_FAILURE; - } - start_of_input_line = isp->u.u_f.advance_line; - output_current_line = -1; - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: input stack botch in pop_input ()")); - abort (); - } - obstack_free (current_input, isp); - next = NULL; /* might be set in push_string_init () */ - - isp = tmp; - input_change = true; -} - -/*------------------------------------------------------------------------. -| To switch input over to the wrapup stack, main () calls pop_wrapup (). | -| Since wrapup text can install new wrapup text, pop_wrapup () returns | -| false when there is no wrapup text on the stack, and true otherwise. | -`------------------------------------------------------------------------*/ - -bool -pop_wrapup (void) -{ - next = NULL; - obstack_free (current_input, NULL); - free (current_input); - - if (wsp == NULL) - { - /* End of the program. Free all memory even though we are about - to exit, since it makes leak detection easier. */ - obstack_free (&token_stack, NULL); - obstack_free (&file_names, NULL); - obstack_free (wrapup_stack, NULL); - free (wrapup_stack); - return false; - } - - current_input = wrapup_stack; - wrapup_stack = (struct obstack *) xmalloc (sizeof (struct obstack)); - obstack_init (wrapup_stack); - - isp = wsp; - wsp = NULL; - input_change = true; - - return true; -} - -/*-------------------------------------------------------------------. -| When a MACRO token is seen, next_token () uses init_macro_token () | -| to retrieve the value of the function pointer. | -`-------------------------------------------------------------------*/ - -static void -init_macro_token (token_data *td) -{ - if (isp->type != INPUT_MACRO) - { - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad call to init_macro_token ()")); - abort (); - } - - TOKEN_DATA_TYPE (td) = TOKEN_FUNC; - TOKEN_DATA_FUNC (td) = isp->u.func; -} - - -/*------------------------------------------------------------------------. -| Low level input is done a character at a time. The function peek_input | -| () 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. | -`------------------------------------------------------------------------*/ - -static int -peek_input (void) -{ - int ch; - input_block *block = isp; - - while (1) - { - if (block == NULL) - return CHAR_EOF; - - switch (block->type) - { - case INPUT_STRING: - ch = to_uchar (block->u.u_s.string[0]); - if (ch != '\0') - return ch; - break; - - case INPUT_FILE: - ch = getc (block->u.u_f.fp); - if (ch != EOF) - { - ungetc (ch, block->u.u_f.fp); - return ch; - } - block->u.u_f.end = true; - break; - - case INPUT_MACRO: - return CHAR_MACRO; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: input stack botch in peek_input ()")); - abort (); - } - block = block->prev; - } -} - -/*-------------------------------------------------------------------------. -| The function next_char () is used to read and advance the input to the | -| next character. It also 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. | -| 99.9% of all calls will read from a string, so factor that out into a | -| macro for speed. | -`-------------------------------------------------------------------------*/ - -#define next_char() \ - (isp && isp->type == INPUT_STRING && isp->u.u_s.string[0] \ - && !input_change \ - ? to_uchar (*isp->u.u_s.string++) \ - : next_char_1 ()) - -static int -next_char_1 (void) -{ - int ch; - - while (1) - { - if (isp == NULL) - { - current_file = ""; - current_line = 0; - return CHAR_EOF; - } - - if (input_change) - { - current_file = isp->file; - current_line = isp->line; - input_change = false; - } - - switch (isp->type) - { - case INPUT_STRING: - ch = to_uchar (*isp->u.u_s.string++); - if (ch != '\0') - return ch; - break; - - case INPUT_FILE: - if (start_of_input_line) - { - start_of_input_line = false; - current_line = ++isp->line; - } - - /* If stdin is a terminal, calling getc after peek_input - already called it would make the user have to hit ^D - twice to quit. */ - ch = isp->u.u_f.end ? EOF : getc (isp->u.u_f.fp); - if (ch != EOF) - { - if (ch == '\n') - start_of_input_line = true; - return ch; - } - break; - - case INPUT_MACRO: - pop_input (); /* INPUT_MACRO input sources has only one - token */ - return CHAR_MACRO; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: input stack botch in next_char ()")); - abort (); - } - - /* End of input source --- pop one level. */ - pop_input (); - } -} - -/*------------------------------------------------------------------------. -| skip_line () simply discards all immediately following characters, upto | -| the first newline. It is only used from m4_dnl (). | -`------------------------------------------------------------------------*/ - -void -skip_line (void) -{ - int ch; - const char *file = current_file; - int line = current_line; - - while ((ch = next_char ()) != CHAR_EOF && ch != '\n') - ; - if (ch == CHAR_EOF) - /* current_file changed to "" if we see CHAR_EOF, use the - previous value we stored earlier. */ - M4ERROR_AT_LINE ((warning_status, 0, file, line, - "Warning: end of file treated as newline")); - /* On the rare occasion that dnl crosses include file boundaries - (either the input file did not end in a newline, or changeword - was used), calling next_char can update current_file and - current_line, and that update will be undone as we return to - expand_macro. This informs next_char to fix things again. */ - if (file != current_file || line != current_line) - input_change = true; -} - - -/*------------------------------------------------------------------. -| This function is for matching a string against a prefix of the | -| input stream. If the string matches the input 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. | -`------------------------------------------------------------------*/ - -static bool -match_input (const char *s, bool consume) -{ - int n; /* number of characters matched */ - int ch; /* input character */ - const char *t; - bool result = false; - - ch = peek_input (); - if (ch != to_uchar (*s)) - return false; /* fail */ - - if (s[1] == '\0') - { - if (consume) - (void) next_char (); - return true; /* short match */ - } - - (void) next_char (); - for (n = 1, t = s++; (ch = peek_input ()) == to_uchar (*s++); ) - { - (void) next_char (); - n++; - if (*s == '\0') /* long match */ - { - if (consume) - return true; - result = true; - break; - } - } - - /* Failed or shouldn't consume, push back input. */ - { - struct obstack *h = push_string_init (); - - /* `obstack_grow' may be macro evaluating its arg 1 several times. */ - obstack_grow (h, t, n); - } - push_string_finish (); - return result; -} - -/*--------------------------------------------------------------------. -| The macro MATCH() is used to match a string S against the input. | -| The first character is handled inline, for speed. Hopefully, this | -| will not hurt efficiency too much when single character quotes and | -| comment delimiters are used. 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(ch, s, consume) \ - (to_uchar ((s)[0]) == (ch) \ - && (ch) != '\0' \ - && ((s)[1] == '\0' || (match_input ((s) + (consume), consume)))) - - -/*----------------------------------------------------------. -| Inititialise input stacks, and quote/comment characters. | -`----------------------------------------------------------*/ - -void -input_init (void) -{ - current_file = ""; - current_line = 0; - - current_input = (struct obstack *) xmalloc (sizeof (struct obstack)); - obstack_init (current_input); - wrapup_stack = (struct obstack *) xmalloc (sizeof (struct obstack)); - obstack_init (wrapup_stack); - - obstack_init (&file_names); - - /* 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); - obstack_alloc (&token_stack, 1); - token_bottom = obstack_base (&token_stack); - - isp = NULL; - wsp = NULL; - next = NULL; - - start_of_input_line = false; - - lquote.string = xstrdup (DEF_LQUOTE); - lquote.length = strlen (lquote.string); - rquote.string = xstrdup (DEF_RQUOTE); - rquote.length = strlen (rquote.string); - bcomm.string = xstrdup (DEF_BCOMM); - bcomm.length = strlen (bcomm.string); - ecomm.string = xstrdup (DEF_ECOMM); - ecomm.length = strlen (ecomm.string); - -#ifdef ENABLE_CHANGEWORD - set_word_regexp (user_word_regexp); -#endif -} - - -/*------------------------------------------------------------------. -| Functions for setting quotes and comment delimiters. Used by | -| m4_changecom () and m4_changequote (). Pass NULL if the argument | -| was not present, to distinguish from an explicit empty string. | -`------------------------------------------------------------------*/ - -void -set_quotes (const char *lq, const char *rq) -{ - free (lquote.string); - free (rquote.string); - - /* 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; - rq = DEF_RQUOTE; - } - else if (!rq || (*lq && !*rq)) - rq = DEF_RQUOTE; - - lquote.string = xstrdup (lq); - lquote.length = strlen (lquote.string); - rquote.string = xstrdup (rq); - rquote.length = strlen (rquote.string); -} - -void -set_comment (const char *bc, const char *ec) -{ - free (bcomm.string); - free (ecomm.string); - - /* POSIX requires no arguments to disable comments. It requires - empty arguments to be used as-is, but this is counter to - traditional behavior, because a non-null begin and null end makes - it impossible to end a comment. An aardvark has been filed: - http://www.opengroup.org/austin/mailarchives/ag-review/msg02168.html - This implementation assumes the aardvark will be approved. See - the texinfo for what some other implementations do. */ - if (!bc) - bc = ec = ""; - else if (!ec || (*bc && !*ec)) - ec = DEF_ECOMM; - - bcomm.string = xstrdup (bc); - bcomm.length = strlen (bcomm.string); - ecomm.string = xstrdup (ec); - ecomm.length = strlen (ecomm.string); -} - -#ifdef ENABLE_CHANGEWORD - -static void -init_pattern_buffer (struct re_pattern_buffer *buf) -{ - buf->translate = NULL; - buf->fastmap = NULL; - buf->buffer = NULL; - buf->allocated = 0; -} - -void -set_word_regexp (const char *regexp) -{ - int i; - char test[2]; - const char *msg; - struct re_pattern_buffer new_word_regexp; - - if (!*regexp || !strcmp (regexp, DEFAULT_WORD_REGEXP)) - { - default_word_regexp = true; - return; - } - - /* Dry run to see whether the new expression is compilable. */ - init_pattern_buffer (&new_word_regexp); - msg = re_compile_pattern (regexp, strlen (regexp), &new_word_regexp); - regfree (&new_word_regexp); - - if (msg != NULL) - { - M4ERROR ((warning_status, 0, - "bad regular expression `%s': %s", regexp, msg)); - return; - } - - /* If compilation worked, retry using the word_regexp struct. - Can't rely on struct assigns working, so redo the compilation. */ - regfree (&word_regexp); - msg = re_compile_pattern (regexp, strlen (regexp), &word_regexp); - re_set_registers (&word_regexp, ®s, regs.num_regs, regs.start, regs.end); - - if (msg != NULL) - { - M4ERROR ((EXIT_FAILURE, 0, - "INTERNAL ERROR: expression recompilation `%s': %s", - regexp, msg)); - } - - default_word_regexp = false; - - if (word_start == NULL) - word_start = (char *) xmalloc (256); - - word_start[0] = '\0'; - test[1] = '\0'; - for (i = 1; i < 256; i++) - { - test[0] = i; - word_start[i] = re_search (&word_regexp, test, 1, 0, 0, NULL) >= 0; - } -} - -#endif /* ENABLE_CHANGEWORD */ - - -/*-------------------------------------------------------------------------. -| Parse and return a single token from the input stream. A token can | -| either be TOKEN_EOF, if the input_stack is empty; it can be TOKEN_STRING | -| for a quoted string; TOKEN_WORD for something that is a potential macro | -| name; and TOKEN_SIMPLE for any single character that is not a part of | -| any of the previous types. | -| | -| Next_token () return the token type, and passes back a pointer to the | -| token data through TD. 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 TD is therefore subject to | -| change the next time next_token () is called. | -`-------------------------------------------------------------------------*/ - -token_type -next_token (token_data *td) -{ - int ch; - int quote_level; - token_type type; -#ifdef ENABLE_CHANGEWORD - int startpos; - char *orig_text = NULL; -#endif - const char *file; - int line; - - obstack_free (&token_stack, token_bottom); - - /* Can't consume character until after CHAR_MACRO is handled. */ - ch = peek_input (); - if (ch == CHAR_EOF) - { -#ifdef DEBUG_INPUT - fprintf (stderr, "next_token -> EOF\n"); -#endif - next_char (); - return TOKEN_EOF; - } - if (ch == CHAR_MACRO) - { - init_macro_token (td); - next_char (); -#ifdef DEBUG_INPUT - fprintf (stderr, "next_token -> MACDEF (%s)\n", - find_builtin_by_addr (TOKEN_DATA_FUNC (td))->name); -#endif - return TOKEN_MACDEF; - } - - next_char (); /* Consume character we already peeked at. */ - file = current_file; - line = current_line; - if (MATCH (ch, bcomm.string, true)) - { - obstack_grow (&token_stack, bcomm.string, bcomm.length); - while ((ch = next_char ()) != CHAR_EOF - && !MATCH (ch, ecomm.string, true)) - obstack_1grow (&token_stack, ch); - if (ch != CHAR_EOF) - obstack_grow (&token_stack, ecomm.string, ecomm.length); - else - /* current_file changed to "" if we see CHAR_EOF, use the - previous value we stored earlier. */ - M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, - "ERROR: end of file in comment")); - - type = TOKEN_STRING; - } - else if (default_word_regexp && (isalpha (ch) || ch == '_')) - { - obstack_1grow (&token_stack, ch); - while ((ch = peek_input ()) != CHAR_EOF && (isalnum (ch) || ch == '_')) - { - obstack_1grow (&token_stack, ch); - (void) next_char (); - } - type = TOKEN_WORD; - } - -#ifdef ENABLE_CHANGEWORD - - else if (!default_word_regexp && word_start[ch]) - { - obstack_1grow (&token_stack, ch); - while (1) - { - ch = peek_input (); - if (ch == CHAR_EOF) - break; - obstack_1grow (&token_stack, ch); - startpos = re_search (&word_regexp, - (char *) obstack_base (&token_stack), - obstack_object_size (&token_stack), 0, 0, - ®s); - if (startpos != 0 || - regs.end [0] != obstack_object_size (&token_stack)) - { - *(((char *) obstack_base (&token_stack) - + obstack_object_size (&token_stack)) - 1) = '\0'; - break; - } - next_char (); - } - - obstack_1grow (&token_stack, '\0'); - orig_text = (char *) obstack_finish (&token_stack); - - if (regs.start[1] != -1) - obstack_grow (&token_stack,orig_text + regs.start[1], - regs.end[1] - regs.start[1]); - else - obstack_grow (&token_stack, orig_text,regs.end[0]); - - type = TOKEN_WORD; - } - -#endif /* ENABLE_CHANGEWORD */ - - else if (!MATCH (ch, lquote.string, true)) - { - switch (ch) - { - case '(': - type = TOKEN_OPEN; - break; - case ',': - type = TOKEN_COMMA; - break; - case ')': - type = TOKEN_CLOSE; - break; - default: - type = TOKEN_SIMPLE; - break; - } - obstack_1grow (&token_stack, ch); - } - else - { - quote_level = 1; - while (1) - { - ch = next_char (); - if (ch == CHAR_EOF) - /* current_file changed to "" if we see CHAR_EOF, use - the previous value we stored earlier. */ - M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, - "ERROR: end of file in string")); - - if (MATCH (ch, rquote.string, true)) - { - if (--quote_level == 0) - break; - obstack_grow (&token_stack, rquote.string, rquote.length); - } - else if (MATCH (ch, lquote.string, true)) - { - quote_level++; - obstack_grow (&token_stack, lquote.string, lquote.length); - } - else - obstack_1grow (&token_stack, ch); - } - type = TOKEN_STRING; - } - - obstack_1grow (&token_stack, '\0'); - - TOKEN_DATA_TYPE (td) = TOKEN_TEXT; - TOKEN_DATA_TEXT (td) = (char *) obstack_finish (&token_stack); -#ifdef ENABLE_CHANGEWORD - if (orig_text == NULL) - orig_text = TOKEN_DATA_TEXT (td); - TOKEN_DATA_ORIG_TEXT (td) = orig_text; -#endif -#ifdef DEBUG_INPUT - fprintf (stderr, "next_token -> %s (%s)\n", - token_type_string (type), TOKEN_DATA_TEXT (td)); -#endif - return type; -} - -/*-----------------------------------------------. -| Peek at the next token from the input stream. | -`-----------------------------------------------*/ - -token_type -peek_token (void) -{ - token_type result; - int ch = peek_input (); - - if (ch == CHAR_EOF) - { - result = TOKEN_EOF; - } - else if (ch == CHAR_MACRO) - { - result = TOKEN_MACDEF; - } - else if (MATCH (ch, bcomm.string, false)) - { - result = TOKEN_STRING; - } - else if ((default_word_regexp && (isalpha (ch) || ch == '_')) -#ifdef ENABLE_CHANGEWORD - || (! default_word_regexp && word_start[ch]) -#endif /* ENABLE_CHANGEWORD */ - ) - { - result = TOKEN_WORD; - } - else if (MATCH (ch, lquote.string, false)) - { - result = TOKEN_STRING; - } - else - switch (ch) - { - case '(': - result = TOKEN_OPEN; - break; - case ',': - result = TOKEN_COMMA; - break; - case ')': - result = TOKEN_CLOSE; - break; - default: - result = TOKEN_SIMPLE; - } - -#ifdef DEBUG_INPUT - fprintf (stderr, "peek_token -> %s\n", token_type_string (result)); -#endif /* DEBUG_INPUT */ - return result; -} - - -#ifdef DEBUG_INPUT - -static const char * -token_type_string (token_type t) -{ - switch (t) - { /* TOKSW */ - case TOKEN_EOF: - return "EOF"; - case TOKEN_STRING: - return "STRING"; - case TOKEN_WORD: - return "WORD"; - case TOKEN_OPEN: - return "OPEN"; - case TOKEN_COMMA: - return "COMMA"; - case TOKEN_CLOSE: - return "CLOSE"; - case TOKEN_SIMPLE: - return "SIMPLE"; - case TOKEN_MACDEF: - return "MACDEF"; - default: - abort (); - } - } - -static void -print_token (const char *s, token_type t, token_data *td) -{ - fprintf (stderr, "%s: ", s); - switch (t) - { /* TOKSW */ - case TOKEN_OPEN: - case TOKEN_COMMA: - case TOKEN_CLOSE: - case TOKEN_SIMPLE: - fprintf (stderr, "char:"); - break; - - case TOKEN_WORD: - fprintf (stderr, "word:"); - break; - - case TOKEN_STRING: - fprintf (stderr, "string:"); - break; - - case TOKEN_MACDEF: - fprintf (stderr, "macro: %p\n", TOKEN_DATA_FUNC (td)); - break; - - case TOKEN_EOF: - fprintf (stderr, "eof\n"); - break; - } - fprintf (stderr, "\t\"%s\"\n", TOKEN_DATA_TEXT (td)); -} - -static void M4_GNUC_UNUSED -lex_debug (void) -{ - token_type t; - token_data td; - - while ((t = next_token (&td)) != TOKEN_EOF) - print_token ("lex", t, &td); -} -#endif diff --git a/src/bin/m4/src/m4.c b/src/bin/m4/src/m4.c deleted file mode 100644 index 98b2582cf8..0000000000 --- a/src/bin/m4/src/m4.c +++ /dev/null @@ -1,581 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include "m4.h" - -#include -#include -#include - -static void usage (int); - -/* Enable sync output for /lib/cpp (-s). */ -int sync_output = 0; - -/* Debug (-d[flags]). */ -int debug_level = 0; - -/* Hash table size (should be a prime) (-Hsize). */ -size_t hash_table_size = HASHMAX; - -/* Disable GNU extensions (-G). */ -int no_gnu_extensions = 0; - -/* Prefix all builtin functions by `m4_'. */ -int prefix_all_builtins = 0; - -/* Max length of arguments in trace output (-lsize). */ -int max_debug_argument_length = 0; - -/* Suppress warnings about missing arguments. */ -int suppress_warnings = 0; - -/* If not zero, then value of exit status for warning diagnostics. */ -int warning_status = 0; - -/* Artificial limit for expansion_level in macro.c. */ -int nesting_limit = 1024; - -#ifdef ENABLE_CHANGEWORD -/* User provided regexp for describing m4 words. */ -const char *user_word_regexp = ""; -#endif - -/* The name this program was run with. */ -const char *program_name; - -struct macro_definition -{ - struct macro_definition *next; - int code; /* D, U, s, t, or '\1' */ - const char *arg; -}; -typedef struct macro_definition macro_definition; - -/* Error handling functions. */ - -/*-----------------------. -| Wrapper around error. | -`-----------------------*/ - -void -m4_error (int status, int errnum, const char *format, ...) -{ - va_list args; - va_start (args, format); - verror_at_line (status, errnum, current_line ? current_file : NULL, - current_line, format, args); -} - -/*-------------------------------. -| Wrapper around error_at_line. | -`-------------------------------*/ - -void -m4_error_at_line (int status, int errnum, const char *file, int line, - const char *format, ...) -{ - va_list args; - va_start (args, format); - verror_at_line (status, errnum, line ? file : NULL, line, format, args); -} - -#ifdef USE_STACKOVF - -/*---------------------------------------. -| Tell user stack overflowed and abort. | -`---------------------------------------*/ - -static void -stackovf_handler (void) -{ - M4ERROR ((EXIT_FAILURE, 0, - "ERROR: stack overflow. (Infinite define recursion?)")); -} - -#endif /* USE_STACKOV */ - - -/*---------------------------------------------. -| Print a usage message and exit with STATUS. | -`---------------------------------------------*/ - -static void -usage (int status) -{ - if (status != EXIT_SUCCESS) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - { - printf ("Usage: %s [OPTION]... [FILE]...\n", program_name); - fputs ("\ -Process macros in FILEs. If no FILE or if FILE is `-', standard input\n\ -is read.\n\ -", stdout); - fputs ("\ -\n\ -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\ - -E, --fatal-warnings stop execution after first warning\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\ -", stdout); -#ifdef ENABLE_CHANGEWORD - fputs ("\ - -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n\ -", stdout); -#endif - fputs ("\ -\n\ -Preprocessor features:\n\ - -D, --define=NAME[=VALUE] define NAME as having VALUE, or empty\n\ - -I, --include=DIRECTORY append DIRECTORY to include path\n\ - -s, --synclines generate `#line NUM \"FILE\"' lines\n\ - -U, --undefine=NAME undefine NAME\n\ -", stdout); - fputs ("\ -\n\ -Limits control:\n\ - -G, --traditional suppress all GNU extensions\n\ - -H, --hashsize=PRIME set symbol lookup hash table size [509]\n\ - -L, --nesting-limit=NUMBER change artificial nesting limit [1024]\n\ -", stdout); - fputs ("\ -\n\ -Frozen state files:\n\ - -F, --freeze-state=FILE produce a frozen state on FILE at end\n\ - -R, --reload-state=FILE reload a frozen state from FILE at start\n\ -", stdout); - fputs ("\ -\n\ -Debugging:\n\ - -d, --debug[=FLAGS] set debug level (no FLAGS implies `aeq')\n\ - --debugfile=FILE redirect debug and trace output\n\ - -l, --arglength=NUM restrict macro tracing size\n\ - -t, --trace=NAME trace NAME when it is defined\n\ -", stdout); - fputs ("\ -\n\ -FLAGS is any of:\n\ - a show actual arguments\n\ - c show before collect, after collect and after call\n\ - e show expansion\n\ - f say current input file name\n\ - i show changes in input files\n\ - l say current input line number\n\ - p show results of path searches\n\ - q quote values as necessary, with a or e flag\n\ - t trace for all macro calls, not only traceon'ed\n\ - x add a unique macro call id, useful with c flag\n\ - V shorthand for all of the above flags\n\ -", stdout); - fputs ("\ -\n\ -If defined, the environment variable `M4PATH' is a colon-separated list\n\ -of directories included after any specified by `-I'.\n\ -", stdout); - fputs ("\ -\n\ -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); - printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT); - } - exit (status); -} - -/*--------------------------------------. -| Decode options and launch execution. | -`--------------------------------------*/ - -/* For long options that have no equivalent short option, use a - non-character as a pseudo short option, starting with CHAR_MAX + 1. */ -enum -{ - DEBUGFILE_OPTION = CHAR_MAX + 1, /* no short opt */ - DIVERSIONS_OPTION, /* not quite -N, because of message */ - - HELP_OPTION, /* no short opt */ - VERSION_OPTION /* no short opt */ -}; - -static const struct option long_options[] = -{ - {"arglength", required_argument, NULL, 'l'}, - {"debug", optional_argument, NULL, 'd'}, - {"define", required_argument, NULL, 'D'}, - {"error-output", required_argument, NULL, 'o'}, /* FIXME: deprecate in 2.0 */ - {"fatal-warnings", no_argument, NULL, 'E'}, - {"freeze-state", required_argument, NULL, 'F'}, - {"hashsize", required_argument, NULL, 'H'}, - {"include", required_argument, NULL, 'I'}, - {"interactive", no_argument, NULL, 'i'}, - {"nesting-limit", required_argument, NULL, 'L'}, - {"prefix-builtins", no_argument, NULL, 'P'}, - {"quiet", no_argument, NULL, 'Q'}, - {"reload-state", required_argument, NULL, 'R'}, - {"silent", no_argument, NULL, 'Q'}, - {"synclines", no_argument, NULL, 's'}, - {"trace", required_argument, NULL, 't'}, - {"traditional", no_argument, NULL, 'G'}, - {"undefine", required_argument, NULL, 'U'}, - {"word-regexp", required_argument, NULL, 'W'}, - - {"debugfile", required_argument, NULL, DEBUGFILE_OPTION}, - {"diversions", required_argument, NULL, DIVERSIONS_OPTION}, - - {"help", no_argument, NULL, HELP_OPTION}, - {"version", no_argument, NULL, VERSION_OPTION}, - - { NULL, 0, NULL, 0 }, -}; - -/* Global catchall for any errors that should affect final error status, but - where we try to continue execution in the meantime. */ -int retcode; - -/* Process a command line file NAME, and return true only if it was - stdin. */ -static bool -process_file (const char *name) -{ - bool result = false; - if (strcmp (name, "-") == 0) - { - /* If stdin is a terminal, we want to allow 'm4 - file -' - to read input from stdin twice, like GNU cat. Besides, - there is no point closing stdin before wrapped text, to - minimize bugs in syscmd called from wrapped text. */ - push_file (stdin, "stdin", false); - result = true; - } - else - { - char *full_name; - FILE *fp = m4_path_search (name, &full_name); - if (fp == NULL) - { - error (0, errno, "%s", name); - /* Set the status to EXIT_FAILURE, even though we - continue to process files after a missing file. */ - retcode = EXIT_FAILURE; - return false; - } - push_file (fp, full_name, true); - free (full_name); - } - expand_input (); - return result; -} - -/* 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. */ -#ifdef ENABLE_CHANGEWORD -#define OPTSTRING "-B:D:EF:GH:I:L:N:PQR:S:T:U:W:d::eil:o:st:" -#else -#define OPTSTRING "-B:D:EF:GH:I:L:N:PQR:S:T:U:d::eil:o:st:" -#endif - -int -main (int argc, char *const *argv, char *const *envp) -{ - macro_definition *head; /* head of deferred argument list */ - macro_definition *tail; - macro_definition *defn; - int optchar; /* option character */ - - macro_definition *defines; - bool read_stdin = false; - bool interactive = false; - bool seen_file = false; - const char *debugfile = NULL; - const char *frozen_file_to_read = NULL; - const char *frozen_file_to_write = NULL; - - program_name = argv[0]; - retcode = EXIT_SUCCESS; - atexit (close_stdout); - - include_init (); - debug_init (); -#ifdef USE_STACKOVF - setup_stackovf_trap (argv, envp, stackovf_handler); -#endif - - /* First, we decode the arguments, to size up tables and stuff. */ - - head = tail = NULL; - - while ((optchar = getopt_long (argc, (char **) argv, OPTSTRING, - long_options, NULL)) != -1) - switch (optchar) - { - default: - usage (EXIT_FAILURE); - - case 'B': - 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: `m4 -%c' may be removed in a future release", - optchar); - break; - - case 'N': - case DIVERSIONS_OPTION: - /* -N became an obsolete no-op in 1.4.x. */ - error (0, 0, "Warning: `m4 %s' is deprecated", - optchar == 'N' ? "-N" : "--diversions"); - - case 'D': - case 'U': - case 's': - case 't': - case '\1': - /* Arguments that cannot be handled until later are accumulated. */ - - defn = (macro_definition *) xmalloc (sizeof (macro_definition)); - defn->code = optchar; - defn->arg = optarg; - defn->next = NULL; - - if (head == NULL) - head = defn; - else - tail->next = defn; - tail = defn; - - break; - - case 'E': - warning_status = EXIT_FAILURE; - break; - - case 'F': - frozen_file_to_write = optarg; - break; - - case 'G': - no_gnu_extensions = 1; - break; - - case 'H': - hash_table_size = atol (optarg); - if (hash_table_size == 0) - hash_table_size = HASHMAX; - break; - - case 'I': - add_include_directory (optarg); - break; - - case 'L': - nesting_limit = atoi (optarg); - break; - - case 'P': - prefix_all_builtins = 1; - break; - - case 'Q': - suppress_warnings = 1; - break; - - case 'R': - frozen_file_to_read = optarg; - break; - -#ifdef ENABLE_CHANGEWORD - case 'W': - user_word_regexp = optarg; - break; -#endif - - case 'd': - debug_level = debug_decode (optarg); - if (debug_level < 0) - { - error (0, 0, "bad debug flags: `%s'", optarg); - debug_level = 0; - } - break; - - case 'e': - error (0, 0, "Warning: `m4 -e' is deprecated, use `-i' instead"); - /* fall through */ - case 'i': - interactive = true; - break; - - case 'l': - max_debug_argument_length = atoi (optarg); - if (max_debug_argument_length <= 0) - max_debug_argument_length = 0; - break; - - case 'o': - /* -o/--error-output are deprecated synonyms of --debugfile, - but don't issue a deprecation warning until autoconf 2.61 - or later is more widely established, as such a warning - would interfere with all earlier versions of autoconf. */ - case DEBUGFILE_OPTION: - /* Don't call debug_set_output here, as it has side effects. */ - debugfile = optarg; - break; - - case VERSION_OPTION: - printf ("%s\n", PACKAGE_STRING); - fputs ("\ -Copyright (C) 2006 Free Software Foundation, Inc.\n\ -This is free software; see the source for copying conditions. There is NO\n\ -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -\n\ -Written by Rene' Seindal.\n\ -", stdout); - exit (EXIT_SUCCESS); - break; - - case HELP_OPTION: - usage (EXIT_SUCCESS); - break; - } - - defines = head; - - /* Do the basic initializations. */ - if (debugfile && !debug_set_output (debugfile)) - M4ERROR ((0, errno, "cannot set debug file `%s'", debugfile)); - - input_init (); - output_init (); - symtab_init (); - include_env_init (); - - if (frozen_file_to_read) - reload_frozen_state (frozen_file_to_read); - else - builtin_init (); - - /* Interactive mode means unbuffered output, and interrupts ignored. */ - - if (interactive) - { - signal (SIGINT, SIG_IGN); - setbuf (stdout, (char *) NULL); - } - - /* Handle deferred command line macro definitions. Must come after - initialization of the symbol table. */ - - while (defines != NULL) - { - macro_definition *next; - symbol *sym; - - switch (defines->code) - { - case 'D': - { - /* defines->arg is read-only, so we need a copy. */ - char *macro_name = xstrdup (defines->arg); - char *macro_value = strchr (macro_name, '='); - if (macro_value) - *macro_value++ = '\0'; - define_user_macro (macro_name, macro_value, SYMBOL_INSERT); - free (macro_name); - } - break; - - case 'U': - lookup_symbol (defines->arg, SYMBOL_DELETE); - break; - - case 't': - sym = lookup_symbol (defines->arg, SYMBOL_INSERT); - SYMBOL_TRACED (sym) = true; - break; - - case 's': - sync_output = 1; - break; - - case '\1': - seen_file = true; - if (process_file (defines->arg)) - read_stdin = true; - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad code in deferred arguments")); - abort (); - } - - next = defines->next; - free (defines); - defines = next; - } - - /* Handle remaining input files. Each file is pushed on the input, - and the input read. Wrapup text is handled separately later. */ - - if (optind == argc && !seen_file) - read_stdin = process_file ("-"); - else - for (; optind < argc; optind++) - if (process_file (defines->arg)) - read_stdin = true; - - /* Now handle wrapup text. */ - - while (pop_wrapup ()) - expand_input (); - - /* Change debug stream back to stderr, to force flushing the debug - stream and detect any errors it might have encountered. Close - stdin if we read from it, to detect any errors. */ - debug_set_output (NULL); - if (read_stdin && fclose (stdin) == EOF) - { - M4ERROR ((warning_status, errno, "error reading file")); - retcode = EXIT_FAILURE; - } - - if (frozen_file_to_write) - produce_frozen_state (frozen_file_to_write); - else - { - make_diversion (0); - undivert_all (); - } - output_exit (); - exit (retcode); -} diff --git a/src/bin/m4/src/m4.h b/src/bin/m4/src/m4.h deleted file mode 100644 index 809da2ec15..0000000000 --- a/src/bin/m4/src/m4.h +++ /dev/null @@ -1,458 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* We use instead of "config.h" so that a compilation - using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h - (which it would do because it found this file in $srcdir). */ - -#include - -#include -#include -#include -#include -#include - -#include "binary-io.h" -#include "clean-temp.h" -#include "cloexec.h" -#include "close-stream.h" -#include "closeout.h" -#include "error.h" -#include "exit.h" -#include "exitfail.h" -#include "obstack.h" -#include "stdio--.h" -#include "stdlib--.h" -#include "unistd--.h" -#include "verror.h" -#include "xalloc.h" -#include "xvasprintf.h" - -/* 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 -#endif - -/* Used for version mismatch, when -R detects a frozen file it can't parse. */ -#define EXIT_MISMATCH 63 - -/* Various declarations. */ - -struct string - { - char *string; /* characters of the string */ - size_t length; /* length of the string */ - }; -typedef struct string STRING; - -/* Memory allocation. */ -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free - -/* Those must come first. */ -typedef struct token_data token_data; -typedef void builtin_func (struct obstack *, int, token_data **); - -/* 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_UNUSED M4_GNUC_ATTRIBUTE((__unused__)) -#define M4_GNUC_PRINTF(fmt, arg) \ - M4_GNUC_ATTRIBUTE((__format__ (__printf__, fmt, arg))) - -/* File: m4.c --- global definitions. */ - -/* Option flags. */ -extern int sync_output; /* -s */ -extern int debug_level; /* -d */ -extern size_t hash_table_size; /* -H */ -extern int no_gnu_extensions; /* -G */ -extern int prefix_all_builtins; /* -P */ -extern int max_debug_argument_length; /* -l */ -extern int suppress_warnings; /* -Q */ -extern int warning_status; /* -E */ -extern int nesting_limit; /* -L */ -#ifdef ENABLE_CHANGEWORD -extern const char *user_word_regexp; /* -W */ -#endif - -/* Error handling. */ -extern int retcode; -extern const char *program_name; - -void m4_error (int, int, const char *, ...) M4_GNUC_PRINTF(3, 4); -void m4_error_at_line (int, int, const char *, int, - const char *, ...) M4_GNUC_PRINTF(5, 6); - -#define M4ERROR(Arglist) (m4_error Arglist) -#define M4ERROR_AT_LINE(Arglist) (m4_error_at_line Arglist) - -#ifdef USE_STACKOVF -void setup_stackovf_trap (char *const *, char *const *, - void (*handler) (void)); -#endif - -/* File: debug.c --- debugging and tracing function. */ - -extern FILE *debug; - -/* The value of debug_level is a bitmask of the following. */ - -/* a: show arglist in trace output */ -#define DEBUG_TRACE_ARGS 1 -/* e: show expansion in trace output */ -#define DEBUG_TRACE_EXPANSION 2 -/* q: quote args and expansion in trace output */ -#define DEBUG_TRACE_QUOTE 4 -/* t: trace all macros -- overrides trace{on,off} */ -#define DEBUG_TRACE_ALL 8 -/* l: add line numbers to trace output */ -#define DEBUG_TRACE_LINE 16 -/* f: add file name to trace output */ -#define DEBUG_TRACE_FILE 32 -/* p: trace path search of include files */ -#define DEBUG_TRACE_PATH 64 -/* c: show macro call before args collection */ -#define DEBUG_TRACE_CALL 128 -/* i: trace changes of input files */ -#define DEBUG_TRACE_INPUT 256 -/* x: add call id to trace output */ -#define DEBUG_TRACE_CALLID 512 - -/* V: very verbose -- print everything */ -#define DEBUG_TRACE_VERBOSE 1023 -/* default flags -- equiv: aeq */ -#define DEBUG_TRACE_DEFAULT 7 - -#define DEBUG_PRINT1(Fmt, Arg1) \ - do \ - { \ - if (debug != NULL) \ - fprintf (debug, Fmt, Arg1); \ - } \ - while (0) - -#define DEBUG_PRINT3(Fmt, Arg1, Arg2, Arg3) \ - do \ - { \ - if (debug != NULL) \ - fprintf (debug, Fmt, Arg1, Arg2, Arg3); \ - } \ - while (0) - -#define DEBUG_MESSAGE(Fmt) \ - do \ - { \ - if (debug != NULL) \ - { \ - debug_message_prefix (); \ - fprintf (debug, Fmt); \ - putc ('\n', debug); \ - } \ - } \ - while (0) - -#define DEBUG_MESSAGE1(Fmt, Arg1) \ - do \ - { \ - if (debug != NULL) \ - { \ - debug_message_prefix (); \ - fprintf (debug, Fmt, Arg1); \ - putc ('\n', debug); \ - } \ - } \ - while (0) - -#define DEBUG_MESSAGE2(Fmt, Arg1, Arg2) \ - do \ - { \ - if (debug != NULL) \ - { \ - debug_message_prefix (); \ - fprintf (debug, Fmt, Arg1, Arg2); \ - putc ('\n', debug); \ - } \ - } \ - while (0) - -void debug_init (void); -int debug_decode (const char *); -void debug_flush_files (void); -bool debug_set_output (const char *); -void debug_message_prefix (void); - -void trace_prepre (const char *, int); -void trace_pre (const char *, int, int, token_data **); -void trace_post (const char *, int, int, token_data **, const char *); - -/* File: input.c --- lexical definitions. */ - -/* Various different token types. */ -enum token_type -{ - TOKEN_EOF, /* end of file */ - TOKEN_STRING, /* a quoted string or comment */ - TOKEN_WORD, /* an identifier */ - TOKEN_OPEN, /* ( */ - TOKEN_COMMA, /* , */ - TOKEN_CLOSE, /* ) */ - TOKEN_SIMPLE, /* any other single character */ - TOKEN_MACDEF /* a macro's definition (see "defn") */ -}; - -/* The data for a token, a macro argument, and a macro definition. */ -enum token_data_type -{ - TOKEN_VOID, - TOKEN_TEXT, - TOKEN_FUNC -}; - -struct token_data -{ - enum token_data_type type; - union - { - struct - { - char *text; -#ifdef ENABLE_CHANGEWORD - char *original_text; -#endif - } - u_t; - builtin_func *func; - } - u; -}; - -#define TOKEN_DATA_TYPE(Td) ((Td)->type) -#define TOKEN_DATA_TEXT(Td) ((Td)->u.u_t.text) -#ifdef ENABLE_CHANGEWORD -# define TOKEN_DATA_ORIG_TEXT(Td) ((Td)->u.u_t.original_text) -#endif -#define TOKEN_DATA_FUNC(Td) ((Td)->u.func) - -typedef enum token_type token_type; -typedef enum token_data_type token_data_type; - -void input_init (void); -token_type peek_token (void); -token_type next_token (token_data *); -void skip_line (void); - -/* push back input */ -void push_file (FILE *, const char *, bool); -void push_macro (builtin_func *); -struct obstack *push_string_init (void); -const char *push_string_finish (void); -void push_wrapup (const char *); -bool pop_wrapup (void); - -/* current input file, and line */ -extern const char *current_file; -extern int current_line; - -/* left and right quote, begin and end comment */ -extern STRING bcomm, ecomm; -extern STRING lquote, rquote; - -#define DEF_LQUOTE "`" -#define DEF_RQUOTE "\'" -#define DEF_BCOMM "#" -#define DEF_ECOMM "\n" - -void set_quotes (const char *, const char *); -void set_comment (const char *, const char *); -#ifdef ENABLE_CHANGEWORD -void set_word_regexp (const char *); -#endif - -/* File: output.c --- output functions. */ -extern int current_diversion; -extern int output_current_line; - -void output_init (void); -void output_exit (void); -void shipout_text (struct obstack *, const char *, int); -void make_diversion (int); -void insert_diversion (int); -void insert_file (FILE *); -void freeze_diversions (FILE *); - -/* File symtab.c --- symbol table definitions. */ - -/* Operation modes for lookup_symbol (). */ -enum symbol_lookup -{ - SYMBOL_LOOKUP, - SYMBOL_INSERT, - SYMBOL_DELETE, - SYMBOL_PUSHDEF, - SYMBOL_POPDEF -}; - -/* Symbol table entry. */ -struct symbol -{ - struct symbol *next; - bool traced : 1; - bool shadowed : 1; - bool macro_args : 1; - bool blind_no_args : 1; - bool deleted : 1; - int pending_expansions; - - char *name; - token_data data; -}; - -#define SYMBOL_NEXT(S) ((S)->next) -#define SYMBOL_TRACED(S) ((S)->traced) -#define SYMBOL_SHADOWED(S) ((S)->shadowed) -#define SYMBOL_MACRO_ARGS(S) ((S)->macro_args) -#define SYMBOL_BLIND_NO_ARGS(S) ((S)->blind_no_args) -#define SYMBOL_DELETED(S) ((S)->deleted) -#define SYMBOL_PENDING_EXPANSIONS(S) ((S)->pending_expansions) -#define SYMBOL_NAME(S) ((S)->name) -#define SYMBOL_TYPE(S) (TOKEN_DATA_TYPE (&(S)->data)) -#define SYMBOL_TEXT(S) (TOKEN_DATA_TEXT (&(S)->data)) -#define SYMBOL_FUNC(S) (TOKEN_DATA_FUNC (&(S)->data)) - -typedef enum symbol_lookup symbol_lookup; -typedef struct symbol symbol; -typedef void hack_symbol (symbol *, void *); - -#define HASHMAX 509 /* default, overridden by -Hsize */ - -extern symbol **symtab; - -void free_symbol (symbol *sym); -void symtab_init (void); -symbol *lookup_symbol (const char *, symbol_lookup); -void hack_all_symbols (hack_symbol *, void *); - -/* File: macro.c --- macro expansion. */ - -void expand_input (void); -void call_macro (symbol *, int, token_data **, struct obstack *); - -/* File: builtin.c --- builtins. */ - -struct builtin -{ - const char *name; - bool gnu_extension : 1; - bool groks_macro_args : 1; - bool blind_if_no_args : 1; - builtin_func *func; -}; - -struct predefined -{ - const char *unix_name; - const char *gnu_name; - const char *func; -}; - -typedef struct builtin builtin; -typedef struct predefined predefined; - -void builtin_init (void); -void define_builtin (const char *, const builtin *, symbol_lookup); -void define_user_macro (const char *, const char *, symbol_lookup); -void undivert_all (void); -void expand_user_macro (struct obstack *, symbol *, int, token_data **); -void m4_placeholder (struct obstack *, int, token_data **); - -const builtin *find_builtin_by_addr (builtin_func *); -const builtin *find_builtin_by_name (const char *); - -/* File: path.c --- path search for include files. */ - -void include_init (void); -void include_env_init (void); -void add_include_directory (const char *); -FILE *m4_path_search (const char *, char **); - -/* File: eval.c --- expression evaluation. */ - -/* eval_t and unsigned_eval_t should be at least 32 bits. */ -typedef int eval_t; -typedef unsigned int unsigned_eval_t; - -bool evaluate (const char *, eval_t *); - -/* File: format.c --- printf like formatting. */ - -void format (struct obstack *, int, token_data **); - -/* File: freeze.c --- frozen state files. */ - -void produce_frozen_state (const char *); -void reload_frozen_state (const char *); - -/* Debugging the memory allocator. */ - -#ifdef WITH_DMALLOC -# define DMALLOC_FUNC_CHECK -# include -#endif - -/* Other debug stuff. */ - -#ifdef DEBUG -# define DEBUG_INCL 1 -# define DEBUG_INPUT 1 -# define DEBUG_MACRO 1 -# define DEBUG_OUTPUT 1 -# define DEBUG_STKOVF 1 -# define DEBUG_SYM 1 -#endif - -/* 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 diff --git a/src/bin/m4/src/m4.rdef b/src/bin/m4/src/m4.rdef deleted file mode 100644 index 0c2ad9a581..0000000000 --- a/src/bin/m4/src/m4.rdef +++ /dev/null @@ -1,11 +0,0 @@ -resource app_version -{ - major = 1, - middle = 4, - minor = 8, - variety = B_APPV_FINAL, - internal = 0, - short_info = "m4", - long_info = "m4 ©2006 The Free Software Foundation" -}; - diff --git a/src/bin/m4/src/macro.c b/src/bin/m4/src/macro.c deleted file mode 100644 index a017ece231..0000000000 --- a/src/bin/m4/src/macro.c +++ /dev/null @@ -1,385 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* This file contains the functions, that performs the basic argument - parsing and macro expansion. */ - -#include "m4.h" - -static void expand_macro (symbol *); -static void expand_token (struct obstack *, token_type, token_data *); - -/* Current recursion level in expand_macro (). */ -int expansion_level = 0; - -/* The number of the current call of expand_macro (). */ -static int macro_call_id = 0; - -/* The shared stack of collected arguments for macro calls; as each - argument is collected, it is finished and its location stored in - argv_stack. Normally, this stack can be used simultaneously by - multiple macro calls; the exception is when an outer macro has - generated some text, then calls a nested macro, in which case the - nested macro must use a local stack to leave the unfinished text - alone. Too bad obstack.h does not provide an easy way to reopen a - finished object for further growth, but in practice this does not - hurt us too much. */ -static struct obstack argc_stack; - -/* The shared stack of pointers to collected arguments for macro - calls. This object is never finished; we exploit the fact that - obstack_blank is documented to take a negative size to reduce the - size again. */ -static struct obstack argv_stack; - -/*----------------------------------------------------------------------. -| This function read all input, and expands each token, one at a time. | -`----------------------------------------------------------------------*/ - -void -expand_input (void) -{ - token_type t; - token_data td; - - obstack_init (&argc_stack); - obstack_init (&argv_stack); - - while ((t = next_token (&td)) != TOKEN_EOF) - expand_token ((struct obstack *) NULL, t, &td); - - obstack_free (&argc_stack, NULL); - obstack_free (&argv_stack, NULL); -} - - -/*------------------------------------------------------------------------. -| Expand one token, according to its type. Potential macro names | -| (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. | -`------------------------------------------------------------------------*/ - -static void -expand_token (struct obstack *obs, token_type t, token_data *td) -{ - symbol *sym; - - switch (t) - { /* TOKSW */ - case TOKEN_EOF: - case TOKEN_MACDEF: - break; - - case TOKEN_OPEN: - case TOKEN_COMMA: - case TOKEN_CLOSE: - case TOKEN_SIMPLE: - case TOKEN_STRING: - shipout_text (obs, TOKEN_DATA_TEXT (td), strlen (TOKEN_DATA_TEXT (td))); - break; - - case TOKEN_WORD: - sym = lookup_symbol (TOKEN_DATA_TEXT (td), SYMBOL_LOOKUP); - if (sym == NULL || SYMBOL_TYPE (sym) == TOKEN_VOID - || (SYMBOL_TYPE (sym) == TOKEN_FUNC - && SYMBOL_BLIND_NO_ARGS (sym) - && peek_token () != TOKEN_OPEN)) - { -#ifdef ENABLE_CHANGEWORD - shipout_text (obs, TOKEN_DATA_ORIG_TEXT (td), - strlen (TOKEN_DATA_ORIG_TEXT (td))); -#else - shipout_text (obs, TOKEN_DATA_TEXT (td), - strlen (TOKEN_DATA_TEXT (td))); -#endif - } - else - expand_macro (sym); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad token type in expand_token ()")); - abort (); - } -} - - -/*-------------------------------------------------------------------------. -| 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, and reads and expands tokens, | -| until it finds a comma or an right parenthesis at the same level of | -| parentheses. It returns a flag indicating whether the argument read are | -| the last for the active macro call. The argument are build on the | -| obstack OBS, indirectly through expand_token (). | -`-------------------------------------------------------------------------*/ - -static bool -expand_argument (struct obstack *obs, token_data *argp) -{ - token_type t; - token_data td; - char *text; - int paren_level; - const char *file = current_file; - int line = current_line; - - TOKEN_DATA_TYPE (argp) = TOKEN_VOID; - - /* Skip leading white space. */ - do - { - t = next_token (&td); - } - while (t == TOKEN_SIMPLE && isspace (to_uchar (*TOKEN_DATA_TEXT (&td)))); - - paren_level = 0; - - while (1) - { - - switch (t) - { /* TOKSW */ - case TOKEN_COMMA: - case TOKEN_CLOSE: - if (paren_level == 0) - { - /* The argument MUST be finished, whether we want it or not. */ - obstack_1grow (obs, '\0'); - text = (char *) obstack_finish (obs); - - if (TOKEN_DATA_TYPE (argp) == TOKEN_VOID) - { - TOKEN_DATA_TYPE (argp) = TOKEN_TEXT; - TOKEN_DATA_TEXT (argp) = text; - } - return t == TOKEN_COMMA; - } - /* fallthru */ - case TOKEN_OPEN: - case TOKEN_SIMPLE: - text = TOKEN_DATA_TEXT (&td); - - if (*text == '(') - paren_level++; - else if (*text == ')') - paren_level--; - expand_token (obs, t, &td); - break; - - case TOKEN_EOF: - /* current_file changed to "" if we see TOKEN_EOF, use the - previous value we stored earlier. */ - M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, - "ERROR: end of file in argument list")); - break; - - case TOKEN_WORD: - case TOKEN_STRING: - expand_token (obs, t, &td); - break; - - case TOKEN_MACDEF: - if (obstack_object_size (obs) == 0) - { - TOKEN_DATA_TYPE (argp) = TOKEN_FUNC; - TOKEN_DATA_FUNC (argp) = TOKEN_DATA_FUNC (&td); - } - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad token type in expand_argument ()")); - abort (); - } - - t = next_token (&td); - } -} - -/*-------------------------------------------------------------------------. -| Collect all the arguments to a call of the macro SYM. The arguments are | -| stored on the obstack ARGUMENTS and a table of pointers to the arguments | -| on the obstack ARGPTR. | -`-------------------------------------------------------------------------*/ - -static void -collect_arguments (symbol *sym, struct obstack *argptr, - struct obstack *arguments) -{ - token_data td; - token_data *tdp; - bool more_args; - bool groks_macro_args = SYMBOL_MACRO_ARGS (sym); - - TOKEN_DATA_TYPE (&td) = TOKEN_TEXT; - TOKEN_DATA_TEXT (&td) = SYMBOL_NAME (sym); - tdp = (token_data *) obstack_copy (arguments, &td, sizeof td); - obstack_ptr_grow (argptr, tdp); - - if (peek_token () == TOKEN_OPEN) - { - next_token (&td); /* gobble parenthesis */ - do - { - more_args = expand_argument (arguments, &td); - - if (!groks_macro_args && TOKEN_DATA_TYPE (&td) == TOKEN_FUNC) - { - TOKEN_DATA_TYPE (&td) = TOKEN_TEXT; - TOKEN_DATA_TEXT (&td) = (char *) ""; - } - tdp = (token_data *) obstack_copy (arguments, &td, sizeof td); - obstack_ptr_grow (argptr, tdp); - } - while (more_args); - } -} - - -/*------------------------------------------------------------------------. -| The actual call of a macro is handled by call_macro (). call_macro () | -| is passed a symbol SYM, whose type is used to call either a builtin | -| function, or the user macro expansion function expand_user_macro () | -| (lives in builtin.c). There are ARGC arguments to the call, stored in | -| the ARGV table. The expansion is left on the obstack EXPANSION. Macro | -| tracing is also handled here. | -`------------------------------------------------------------------------*/ - -void -call_macro (symbol *sym, int argc, token_data **argv, - struct obstack *expansion) -{ - switch (SYMBOL_TYPE (sym)) - { - case TOKEN_FUNC: - (*SYMBOL_FUNC (sym)) (expansion, argc, argv); - break; - - case TOKEN_TEXT: - expand_user_macro (expansion, sym, argc, argv); - break; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: bad symbol type in call_macro ()")); - abort (); - } -} - -/*-------------------------------------------------------------------------. -| 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 call_macro () 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 (). | -`-------------------------------------------------------------------------*/ - -static void -expand_macro (symbol *sym) -{ - struct obstack arguments; /* Alternate obstack if argc_stack is busy. */ - unsigned argv_base; /* Size of argv_stack on entry. */ - bool use_argc_stack = true; /* Whether argc_stack is safe. */ - token_data **argv; - int argc; - struct obstack *expansion; - const char *expanded; - bool traced; - int my_call_id; - - /* Report errors at the location where the open parenthesis (if any) - was found, but after expansion, restore global state back to the - location of the close parenthesis. This is safe since we - guarantee that macro expansion does not alter the state of - current_file/current_line (dnl, include, and sinclude are special - cased in the input engine to ensure this fact). */ - const char *loc_open_file = current_file; - int loc_open_line = current_line; - const char *loc_close_file; - int loc_close_line; - - SYMBOL_PENDING_EXPANSIONS (sym)++; - expansion_level++; - if (nesting_limit > 0 && expansion_level > nesting_limit) - M4ERROR ((EXIT_FAILURE, 0, - "ERROR: recursion limit of %d exceeded, use -L to change it", - nesting_limit)); - - macro_call_id++; - my_call_id = macro_call_id; - - traced = (debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym); - - argv_base = obstack_object_size (&argv_stack); - if (obstack_object_size (&argc_stack) > 0) - { - /* We cannot use argc_stack if this is a nested invocation, and an - outer invocation has an unfinished argument being - collected. */ - obstack_init (&arguments); - use_argc_stack = false; - } - - if (traced && (debug_level & DEBUG_TRACE_CALL)) - trace_prepre (SYMBOL_NAME (sym), my_call_id); - - collect_arguments (sym, &argv_stack, - use_argc_stack ? &argc_stack : &arguments); - - argc = ((obstack_object_size (&argv_stack) - argv_base) - / sizeof (token_data *)); - argv = (token_data **) ((char *) obstack_base (&argv_stack) + argv_base); - - loc_close_file = current_file; - loc_close_line = current_line; - current_file = loc_open_file; - current_line = loc_open_line; - - if (traced) - trace_pre (SYMBOL_NAME (sym), my_call_id, argc, argv); - - expansion = push_string_init (); - call_macro (sym, argc, argv, expansion); - expanded = push_string_finish (); - - if (traced) - trace_post (SYMBOL_NAME (sym), my_call_id, argc, argv, expanded); - - current_file = loc_close_file; - current_line = loc_close_line; - - --expansion_level; - --SYMBOL_PENDING_EXPANSIONS (sym); - - if (SYMBOL_DELETED (sym)) - free_symbol (sym); - - if (use_argc_stack) - obstack_free (&argc_stack, argv[0]); - else - obstack_free (&arguments, NULL); - obstack_blank (&argv_stack, -argc * sizeof (token_data *)); -} diff --git a/src/bin/m4/src/output.c b/src/bin/m4/src/output.c deleted file mode 100644 index d482bf7504..0000000000 --- a/src/bin/m4/src/output.c +++ /dev/null @@ -1,815 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include "m4.h" - -#include -#include - -#include "gl_avltree_oset.h" - -/* 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 - file has been created). 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; /* in-memory diversion buffer */ - m4_diversion *next; /* free-list pointer */ - } u; - int divnum; /* which diversion this represents */ - int size; /* usable size before reallocation */ - int used; /* used length in characters */ - }; - -/* Table 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 struct obstack diversion_storage; - -/* Total size of all in-memory buffer sizes. */ -static int total_buffer_size; - -/* The number of the currently active diversion. This variable is - maintained for the `divnum' builtin function. */ -int current_diversion; - -/* Current output diversion, NULL if output is being currently discarded. */ -static m4_diversion *output_diversion; - -/* Values of some output_diversion fields, cached out for speed. */ -static FILE *output_file; /* current value of (file) */ -static char *output_cursor; /* current value of (buffer + used) */ -static int output_unused; /* current value of (size - used) */ - -/* Number of input line we are generating output for. */ -int output_current_line; - -/* Temporary directory holding all spilled diversion files. */ -static m4_temp_dir *output_temp_dir; - - - -/*------------------------. -| Output initialization. | -`------------------------*/ - -/* 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 *div = (const m4_diversion *) elt; - /* No need to worry about overflow, since we don't create diversions - with negative divnum. */ - return div->divnum >= *(const int *) threshold; -} - -void -output_init (void) -{ - diversion_table = gl_oset_create_empty (GL_AVLTREE_OSET, cmp_diversion_CB); - div0.u.file = stdout; - output_diversion = &div0; - output_file = stdout; - obstack_init (&diversion_storage); -} - -void -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; - diversion_table = NULL; - gl_oset_free (table); - obstack_free (&diversion_storage, NULL); -} - -/* 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) - { - M4ERROR ((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 char *tail; - if (buffer == NULL) - { - tail = xasprintf ("%s/m4-%d", output_temp_dir->dir_name, INT_MAX); - buffer = obstack_copy0 (&diversion_storage, tail, strlen (tail)); - free (tail); - tail = strrchr (buffer, '-') + 1; - } - sprintf (tail, "%d", divnum); - 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; 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 (int divnum) -{ - const char *name; - FILE *file; - - if (output_temp_dir == NULL) - { - errno = 0; - output_temp_dir = create_temp_dir ("m4-", NULL, true); - if (output_temp_dir == NULL) - M4ERROR ((EXIT_FAILURE, errno, - "cannot create temporary file for diversion")); - atexit (cleanup_tmpfile); - } - name = m4_tmpname (divnum); - register_temp_file (output_temp_dir, name); - errno = 0; - file = fopen_temp (name, O_BINARY ? "wb+" : "w+"); - if (file == NULL) - { - unregister_temp_file (output_temp_dir, name); - M4ERROR ((EXIT_FAILURE, errno, - "cannot create temporary file for diversion")); - } - else if (set_cloexec_flag (fileno (file), true) != 0) - M4ERROR ((warning_status, errno, - "Warning: cannot protect diversion across forks")); - return file; -} - -/* Reopen a temporary file for diversion DIVNUM for reading and - writing in a secure temp directory. Exits on failure, so the - return value is always an open file. */ -static FILE * -m4_tmpopen (int divnum) -{ - const char *name = m4_tmpname (divnum); - FILE *file; - - errno = 0; - file = fopen_temp (name, O_BINARY ? "ab+" : "a+"); - if (file == NULL) - M4ERROR ((EXIT_FAILURE, errno, - "cannot create temporary file for diversion")); - else if (set_cloexec_flag (fileno (file), true) != 0) - M4ERROR ((warning_status, errno, - "Warning: cannot protect diversion across forks")); - return file; -} - -/* Close, but don't delete, a temporary FILE. */ -static int -m4_tmpclose (FILE *file) -{ - return close_stream_temp (file); -} - -/* Delete a closed temporary FILE for diversion DIVNUM. */ -static int -m4_tmpremove (int divnum) -{ - return cleanup_temp_file (output_temp_dir, m4_tmpname (divnum)); -} - -/*-----------------------------------------------------------------------. -| 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 (int length) -{ - int wanted_size; - m4_diversion *selected_diversion = NULL; - - /* 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 < 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) - { - int selected_used; - char *selected_buffer; - m4_diversion *diversion; - int 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 (selected_diversion->divnum); - - if (selected_diversion->used > 0) - { - count = fwrite (selected_buffer, (size_t) selected_diversion->used, - 1, selected_diversion->u.file); - if (count != 1) - M4ERROR ((EXIT_FAILURE, errno, - "ERROR: 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 = 0; - if (m4_tmpclose (file) != 0) - M4ERROR ((0, errno, "cannot close temporary file for diversion")); - } - - /* The current buffer may be safely reallocated. */ - output_diversion->u.buffer - = xrealloc (output_diversion->u.buffer, (size_t) wanted_size); - - 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. | -`------------------------------------------------------------------------*/ - -#define OUTPUT_CHARACTER(Char) \ - if (output_file) \ - putc ((Char), output_file); \ - else if (output_unused == 0) \ - output_character_helper ((Char)); \ - else \ - (output_unused--, *output_cursor++ = (Char)) - -static void -output_character_helper (int character) -{ - make_room_for (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. | -`------------------------------------------------------------------------*/ - -static void -output_text (const char *text, int length) -{ - int count; - - if (!output_file && length > output_unused) - make_room_for (length); - - if (output_file) - { - count = fwrite (text, length, 1, output_file); - if (count != 1) - M4ERROR ((EXIT_FAILURE, errno, "ERROR: copying inserted file")); - } - else - { - memcpy (output_cursor, text, (size_t) length); - output_cursor += length; - output_unused -= length; - } -} - -/*-------------------------------------------------------------------------. -| Add some text into an obstack OBS, taken from TEXT, having LENGTH | -| characters. If OBS is NULL, rather output the text to an external file | -| or an in-memory diversion buffer. If OBS is NULL, and there is no | -| output file, the text is discarded. | -| | -| If we are generating sync lines, the output have 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 lines generates several | -| output lines, or when several input lines does not generate any output. | -`-------------------------------------------------------------------------*/ - -void -shipout_text (struct obstack *obs, const char *text, int length) -{ - static bool start_of_output_line = true; - char line[20]; - const char *cursor; - - /* 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 == NULL) - return; - - /* Output TEXT to a file, or in-memory diversion buffer. */ - - if (!sync_output) - 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: - output_text (text, length); - } - else - for (; length-- > 0; text++) - { - if (start_of_output_line) - { - start_of_output_line = false; - output_current_line++; - -#ifdef DEBUG_OUTPUT - printf ("DEBUG: cur %d, cur out %d\n", - current_line, output_current_line); -#endif - - /* Output a `#line NUM' synchronization directive if needed. - If output_current_line was previously given a negative - value (invalidated), rather output `#line NUM "FILE"'. */ - - if (output_current_line != current_line) - { - sprintf (line, "#line %d", current_line); - for (cursor = line; *cursor; cursor++) - OUTPUT_CHARACTER (*cursor); - if (output_current_line < 1 && current_file[0] != '\0') - { - OUTPUT_CHARACTER (' '); - OUTPUT_CHARACTER ('"'); - for (cursor = current_file; *cursor; cursor++) - OUTPUT_CHARACTER (*cursor); - OUTPUT_CHARACTER ('"'); - } - OUTPUT_CHARACTER ('\n'); - output_current_line = current_line; - } - } - OUTPUT_CHARACTER (*text); - if (*text == '\n') - start_of_output_line = true; - } -} - -/* 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 -make_diversion (int divnum) -{ - m4_diversion *diversion = NULL; - - if (current_diversion == divnum) - return; - - if (output_diversion) - { - if (!output_diversion->size && !output_diversion->u.file) - { - if (!gl_oset_remove (diversion_table, output_diversion)) - error (EXIT_FAILURE, 0, "INTERNAL ERROR: make_diversion failed"); - output_diversion->u.next = free_list; - output_diversion->used = 0; - free_list = output_diversion; - } - else if (output_diversion->size) - output_diversion->used = output_diversion->size - output_unused; - else if (output_diversion->used) - { - FILE *file = output_diversion->u.file; - output_diversion->u.file = NULL; - if (m4_tmpclose (file) != 0) - M4ERROR ((0, errno, "cannot close temporary file for diversion")); - } - output_diversion = NULL; - output_file = NULL; - output_cursor = NULL; - output_unused = 0; - } - - current_diversion = 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; - } - else - { - diversion = (m4_diversion *) obstack_alloc (&diversion_storage, - sizeof *diversion); - diversion->size = 0; - diversion->used = 0; - } - diversion->u.file = NULL; - diversion->divnum = divnum; - gl_oset_add (diversion_table, diversion); - } - - 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 (output_diversion->divnum); - output_file = output_diversion->u.file; - } - output_current_line = -1; -} - -/*-------------------------------------------------------------------. -| 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 -insert_file (FILE *file) -{ - char buffer[COPY_BUFFER_SIZE]; - size_t length; - - /* Optimize out inserting into a sink. */ - - if (!output_diversion) - return; - - /* Insert output by big chunks. */ - - for (;;) - { - length = fread (buffer, 1, COPY_BUFFER_SIZE, file); - if (ferror (file)) - M4ERROR ((EXIT_FAILURE, errno, "ERROR: reading inserted file")); - if (length == 0) - break; - output_text (buffer, length); - } -} - -/*-------------------------------------------------------------------. -| Insert DIVERSION (but not div0) 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. | -`-------------------------------------------------------------------*/ - -static void -insert_diversion_helper (m4_diversion *diversion) -{ - /* Effectively undivert only if an output stream is active. */ - if (output_diversion) - { - if (diversion->size) - output_text (diversion->u.buffer, diversion->used); - else - { - if (!diversion->u.file && diversion->used) - diversion->u.file = m4_tmpopen (diversion->divnum); - if (diversion->u.file) - { - rewind (diversion->u.file); - insert_file (diversion->u.file); - } - } - - output_current_line = -1; - } - - /* Return all space used by the diversion. */ - if (diversion->size) - { - free (diversion->u.buffer); - diversion->size = 0; - diversion->used = 0; - } - else - { - if (diversion->u.file) - { - FILE *file = diversion->u.file; - diversion->u.file = NULL; - diversion->used = 0; - if (m4_tmpclose (file) != 0) - M4ERROR ((0, errno, "cannot clean temporary file for diversion")); - } - if (m4_tmpremove (diversion->divnum) != 0) - M4ERROR ((0, errno, "cannot clean temporary file for diversion")); - } - gl_oset_remove (diversion_table, diversion); - 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 -insert_diversion (int divnum) -{ - const void *elt; - - /* Do not care about nonexistent diversions, and undiverting stdout - or self is a no-op. */ - if (divnum <= 0 || current_diversion == 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 (diversion); - } -} - -/*-------------------------------------------------------------------------. -| Get back all diversions. This is done just before exiting from main (), | -| and from m4_undivert (), if called without arguments. | -`-------------------------------------------------------------------------*/ - -void -undivert_all (void) -{ - 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 != current_diversion) - insert_diversion_helper (diversion); - } - gl_oset_iterator_free (&iter); -} - -/*-------------------------------------------------------------. -| Produce all diversion information in frozen format on FILE. | -`-------------------------------------------------------------*/ - -void -freeze_diversions (FILE *file) -{ - int saved_number; - int last_inserted; - gl_oset_iterator_t iter; - const void *elt; - - saved_number = current_diversion; - last_inserted = 0; - make_diversion (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->u.file) - { - if (diversion->size) - fprintf (file, "D%d,%d\n", diversion->divnum, diversion->used); - else - { - struct stat file_stat; - fflush (diversion->u.file); - if (fstat (fileno (diversion->u.file), &file_stat) < 0) - M4ERROR ((EXIT_FAILURE, errno, "cannot stat diversion")); - if (file_stat.st_size < 0 - || file_stat.st_size != (unsigned long int) file_stat.st_size) - M4ERROR ((EXIT_FAILURE, 0, "diversion too large")); - fprintf (file, "D%d,%lu", diversion->divnum, - (unsigned long int) file_stat.st_size); - } - - insert_diversion_helper (diversion); - 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) - fprintf (file, "D%d,0\n\n", saved_number); -} diff --git a/src/bin/m4/src/path.c b/src/bin/m4/src/path.c deleted file mode 100644 index 634b1ec641..0000000000 --- a/src/bin/m4/src/path.c +++ /dev/null @@ -1,193 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 2004, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* Handling of path search of included files via the builtins "include" - and "sinclude". */ - -#include "m4.h" - -struct includes -{ - struct includes *next; /* next directory to search */ - const char *dir; /* directory */ - int len; -}; - -typedef struct includes includes; - -static includes *dir_list; /* the list of path directories */ -static includes *dir_list_end; /* the end of same */ -static int dir_max_length; /* length of longest directory name */ - - -void -include_init (void) -{ - dir_list = NULL; - dir_list_end = NULL; - dir_max_length = 0; -} - -void -include_env_init (void) -{ - char *path; - char *path_end; - char *env_path; - - if (no_gnu_extensions) - return; - - env_path = getenv ("M4PATH"); - if (env_path == NULL) - return; - - env_path = xstrdup (env_path); - path = env_path; - - do - { - path_end = strchr (path, ':'); - if (path_end) - *path_end = '\0'; - add_include_directory (path); - path = path_end + 1; - } - while (path_end); - free (env_path); -} - -void -add_include_directory (const char *dir) -{ - includes *incl; - - if (no_gnu_extensions) - return; - - if (*dir == '\0') - dir = "."; - - incl = (includes *) xmalloc (sizeof (struct includes)); - incl->next = NULL; - incl->len = strlen (dir); - incl->dir = xstrdup (dir); - - if (incl->len > dir_max_length) /* remember len of longest directory */ - dir_max_length = incl->len; - - if (dir_list_end == NULL) - dir_list = incl; - else - dir_list_end->next = incl; - dir_list_end = incl; - -#ifdef DEBUG_INCL - fprintf (stderr, "add_include_directory (%s);\n", dir); -#endif -} - -/* Search for FILE, first in `.', then according to -I options. 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. */ - -FILE * -m4_path_search (const char *file, char **result) -{ - FILE *fp; - includes *incl; - char *name; /* buffer for constructed name */ - int e; - - if (result) - *result = NULL; - - /* Reject empty file. */ - if (!*file) - { - errno = ENOENT; - return NULL; - } - - /* Look in current working directory first. */ - fp = fopen (file, "r"); - if (fp != NULL) - { - if (set_cloexec_flag (fileno (fp), true) != 0) - M4ERROR ((warning_status, errno, - "Warning: cannot protect input file across forks")); - if (result) - *result = xstrdup (file); - return fp; - } - - /* If file not found, and filename absolute, fail. */ - if (*file == '/' || no_gnu_extensions) - return NULL; - e = errno; - - name = (char *) xmalloc (dir_max_length + 1 + strlen (file) + 1); - - for (incl = dir_list; incl != NULL; incl = incl->next) - { - strncpy (name, incl->dir, incl->len); - name[incl->len] = '/'; - strcpy (name + incl->len + 1, file); - -#ifdef DEBUG_INCL - fprintf (stderr, "m4_path_search (%s) -- trying %s\n", file, name); -#endif - - fp = fopen (name, "r"); - if (fp != NULL) - { - if (debug_level & DEBUG_TRACE_PATH) - DEBUG_MESSAGE2 ("path search for `%s' found `%s'", file, name); - if (set_cloexec_flag (fileno (fp), true) != 0) - M4ERROR ((warning_status, errno, - "Warning: cannot protect input file across forks")); - if (result) - *result = name; - else - free (name); - errno = e; - return fp; - } - } - free (name); - errno = e; - return fp; -} - -#ifdef DEBUG_INCL - -static void M4_GNUC_UNUSED -include_dump (void) -{ - includes *incl; - - fprintf (stderr, "include_dump:\n"); - for (incl = dir_list; incl != NULL; incl = incl->next) - fprintf (stderr, "\t%s\n", incl->dir); -} - -#endif /* DEBUG_INCL */ diff --git a/src/bin/m4/src/stackovf.c b/src/bin/m4/src/stackovf.c deleted file mode 100644 index 2aae507643..0000000000 --- a/src/bin/m4/src/stackovf.c +++ /dev/null @@ -1,415 +0,0 @@ -/* Detect stack overflow (when getrlimit and sigaction or sigvec are available) - Copyright (C) 1993, 1994, 2006 Free Software Foundation, Inc. - Jim Avera , October 1993. - - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - */ - -/* 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." */ - -#include "m4.h" /* stdlib.h, xmalloc() */ - -#include -#include -#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); - -static const char *stackbot; -static const char *stackend; -static const char *arg0; -static handler_t stackovf_handler; - -/* The following OS-independent procedure is called from the SIGSEGV - signal handler. The signal handler obtains information about the trap - in an OS-dependent manner, and passes a parameter with the meanings as - explained below. - - If the OS explicitly identifies a stack overflow trap, either pass - PARAM_STACKOVF if a stack overflow, or pass PARAM_NOSTACKOVF if not - (id est, it is a random bounds violation). Otherwise, if the fault - address is available, pass the fault address. Otherwise (if no - information is available), pass NULL. - - Not given an explicit indication, we compare the fault address with - the estimated stack limit, and test to see if overall VM space is - exhausted. - - If a stack overflow is identified, then the external *stackovf_handler - function is called, which should print an error message and exit. If - it is NOT a stack overflow, then we silently abort with a core dump by - returning to re-raise the SIGSEGV with SIG_DFL set. If indeterminate, - then we do not call *stackovf_handler, but instead print an ambiguous - message and abort with a core dump. This only occurs on systems which - provide no information, but is better than nothing. */ - -#define PARAM_STACKOVF ((const char *) (1 + STACKOVF_DETECT)) -#define PARAM_NOSTACKOVF ((const char *) (2 + STACKOVF_DETECT)) - -static void -process_sigsegv (int signo, const char *p) -{ - long diff; - diff = (p - stackend); - -#ifdef DEBUG_STKOVF - { - char buf[140]; - - sprintf (buf, "process_sigsegv: p=%#lx stackend=%#lx diff=%ld bot=%#lx\n", - (long) p, (long) stackend, (long) diff, (long) stackbot); - write (2, buf, strlen (buf)); - } -#endif - - if (p != PARAM_NOSTACKOVF) - { - if ((long) sbrk (8192) == (long) -1) - { - - /* sbrk failed. Assume the RLIMIT_VMEM prevents expansion even - if the stack limit has not been reached. */ - - write (2, "VMEM limit exceeded?\n", 21); - p = PARAM_STACKOVF; - } - if (diff >= -STACKOVF_DETECT && diff <= STACKOVF_DETECT) - { - - /* The fault address is "sufficiently close" to the stack lim. */ - - p = PARAM_STACKOVF; - } - if (p == PARAM_STACKOVF) - { - - /* We have determined that this is indeed a stack overflow. */ - - (*stackovf_handler) (); /* should call exit() */ - } - } - if (p == NULL) - { - const char *cp; - - cp = "\ -Memory bounds violation detected (SIGSEGV). Either a stack overflow\n\ -occurred, or there is a bug in "; - write (2, cp, strlen (cp)); - write (2, arg0, strlen (arg0)); - cp = ". Check for possible infinite recursion.\n"; - write (2, cp, strlen (cp)); - } - - /* Return to re-execute the instruction which caused the trap with - SIGSEGV set to SIG_DFL. An abort with core dump should occur. */ - - signal (signo, SIG_DFL); -} - -#if HAVE_STRUCT_SIGACTION_SA_SIGACTION - -/* POSIX. */ - -static void -sigsegv_handler (int signo, siginfo_t *ip, void *context) -{ - process_sigsegv - (signo, (ip != NULL - && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL)); -} - -#elif HAVE_SIGINFO_T - -/* SVR4. */ - -static void -sigsegv_handler (int signo, siginfo_t *ip) -{ - process_sigsegv - (signo, (ip != NULL - && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL)); -} - -#elif HAVE_SIGCONTEXT - -/* SunOS 4.x (and BSD?). (not tested) */ - -static void -sigsegv_handler (int signo, int code, struct sigcontext *scp, char *addr) -{ - process_sigsegv (signo, addr); -} - -#else /* not HAVE_SIGCONTEXT */ - -/* OS provides no information. */ - -static void -sigsegv_handler (int signo) -{ - process_sigsegv (signo, NULL); -} - -#endif /* not HAVE_SIGCONTEXT */ - -/* Arrange to trap a stack-overflow and call a specified handler. The - call is on a dedicated signal stack. - - argv and envp are as passed to main(). - - If a stack overflow is not detected, then the SIGSEGV is re-raised - with action set to SIG_DFL, causing an abort and coredump in the usual - way. - - Detection of a stack overflow depends on the trap address being near - the stack limit address. The stack limit can not be directly - determined in a portable way, but we make an estimate based on the - address of the argv and environment vectors, their contents, and the - maximum stack size obtained using getrlimit. */ - -void -setup_stackovf_trap (char *const *argv, char *const *envp, handler_t handler) -{ - struct rlimit rl; - rlim_t stack_len; - int grows_upward; - register char *const *v; - register char *p; -#if HAVE_SIGACTION && defined SA_ONSTACK - struct sigaction act; -#elif HAVE_SIGVEC && defined SV_ONSTACK - struct sigvec vec; -#else - -Error - Do not know how to set up stack-ovf trap handler... - -#endif - - arg0 = argv[0]; - stackovf_handler = handler; - - /* Calculate the approximate expected addr for a stack-ovf trap. */ - - if (getrlimit (RLIMIT_STACK, &rl) < 0) - error (EXIT_FAILURE, errno, "getrlimit"); - stack_len = (rl.rlim_cur < rl.rlim_max ? rl.rlim_cur : rl.rlim_max); - stackbot = (char *) argv; - grows_upward = ((char *) &stack_len > stackbot); - if (grows_upward) - { - - /* Grows toward increasing addresses. */ - - for (v = argv; (p = (char *) *v) != NULL; v++) - { - if (p < stackbot) - stackbot = p; - } - if ((char *) envp < stackbot) - stackbot = (char *) envp; - for (v = envp; (p = (char *) *v) != NULL; v++) - { - if (p < stackbot) - stackbot = p; - } - stackend = stackbot + stack_len; - } - else - { - - /* The stack grows "downward" (toward decreasing addresses). */ - - for (v = argv; (p = (char *) *v) != NULL; v++) - { - if (p > stackbot) - stackbot = p; - } - if ((char *) envp > stackbot) - stackbot = (char *) envp; - for (v = envp; (p = (char *) *v) != NULL; v++) - { - if (p > stackbot) - stackbot = p; - } - stackend = stackbot - stack_len; - } - - /* Allocate a separate signal-handler stack. */ - -#if HAVE_SIGALTSTACK && (HAVE_SIGINFO_T || ! HAVE_SIGSTACK) - - /* Use sigaltstack only if siginfo_t is available, unless there is no - choice. */ - - { - stack_t ss; - - ss.ss_size = SIGSTKSZ; - ss.ss_sp = xmalloc ((unsigned) ss.ss_size); - ss.ss_flags = 0; - if (sigaltstack (&ss, NULL) < 0) - { - /* Oops - sigaltstack exists but doesn't work. We can't - install the overflow detector, but should gracefully treat - it as though sigaltstack doesn't exist. For example, this - happens when compiled with Linux 2.1 headers but run - against Linux 2.0 kernel. */ - free (ss.ss_sp); - if (errno == ENOSYS) - return; - error (EXIT_FAILURE, errno, "sigaltstack"); - } - } - -#elif HAVE_SIGSTACK - - { - struct sigstack ss; - char *stackbuf = xmalloc (2 * SIGSTKSZ); - - ss.ss_sp = stackbuf + SIGSTKSZ; - ss.ss_onstack = 0; - if (sigstack (&ss, NULL) < 0) - { - /* Oops - sigstack exists but doesn't work. We can't install - the overflow detector, but should gracefully treat it as - though sigstack doesn't exist. For example, this happens - when compiled with Linux 2.1 headers but run against Linux - 2.0 kernel. */ - free (stackbuf); - if (errno == ENOSYS) - return; - error (EXIT_FAILURE, errno, "sigstack"); - } - } - -#else /* not HAVE_SIGSTACK */ - -Error - Do not know how to set up stack-ovf trap handler... - -#endif /* not HAVE_SIGSTACK */ - - /* Arm the SIGSEGV signal handler. */ - -#if HAVE_SIGACTION && defined SA_ONSTACK - - sigaction (SIGSEGV, NULL, &act); -# if HAVE_STRUCT_SIGACTION_SA_SIGACTION - act.sa_sigaction = sigsegv_handler; -# else /* ! HAVE_STRUCT_SIGACTION_SA_SIGACTION */ - act.sa_handler = (RETSIGTYPE (*) (int)) sigsegv_handler; -# endif /* ! HAVE_STRUCT_SIGACTION_SA_SIGACTION */ - sigemptyset (&act.sa_mask); - act.sa_flags = (SA_ONSTACK | SA_RESETHAND | SA_SIGINFO); - if (sigaction (SIGSEGV, &act, NULL) < 0) - error (EXIT_FAILURE, errno, "sigaction"); - -#else /* ! HAVE_SIGACTION */ - - vec.sv_handler = (RETSIGTYPE (*) (int)) sigsegv_handler; - vec.sv_mask = 0; - vec.sv_flags = (SV_ONSTACK | SV_RESETHAND); - if (sigvec (SIGSEGV, &vec, NULL) < 0) - error (EXIT_FAILURE, errno, "sigvec"); - -#endif /* ! HAVE_SIGACTION */ - -} diff --git a/src/bin/m4/src/symtab.c b/src/bin/m4/src/symtab.c deleted file mode 100644 index 4fadf884ac..0000000000 --- a/src/bin/m4/src/symtab.c +++ /dev/null @@ -1,403 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2003, 2006 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -/* This file handles all the low level work around the symbol table. The - symbol table is a simple chained hash table. Each symbol is described - by a struct symbol, which is placed in the hash table based upon the - symbol name. Symbols that hash to the same entry in the table are - kept on a list, sorted by name. As a special case, to facilitate the - "pushdef" and "popdef" builtins, a symbol can be several times in the - symbol table, one for each definition. Since the name is the same, - all the entries for the symbol will be on the same list, and will - also, because the list is sorted, be adjacent. All the entries for a - name are simply ordered on the list by age. The current definition - will then always be the first found. */ - -#include "m4.h" -#include - -#ifdef DEBUG_SYM -/* When evaluating hash table performance, this profiling code shows - how many collisions were encountered. */ - -struct profile -{ - int entry; /* Number of times lookup_symbol called with this mode. */ - int comparisons; /* Number of times strcmp was called. */ - int misses; /* Number of times strcmp did not return 0. */ - long long bytes; /* Number of bytes compared. */ -}; - -static struct profile profiles[5]; -static symbol_lookup current_mode; - -/* On exit, show a profile of symbol table performance. */ -static void -show_profile (void) -{ - int i; - for (i = 0; i < 5; i++) - { - fprintf(stderr, "m4: lookup mode %d called %d times, %d compares, " - "%d misses, %lld bytes\n", - i, profiles[i].entry, profiles[i].comparisons, - profiles[i].misses, profiles[i].bytes); - } -} - -/* Like strcmp (S1, S2), but also track profiling statistics. */ -static int -profile_strcmp (const char *s1, const char *s2) -{ - int i = 1; - int result; - while (*s1 && *s1 == *s2) - { - s1++; - s2++; - i++; - } - result = (unsigned char) *s1 - (unsigned char) *s2; - profiles[current_mode].comparisons++; - if (result != 0) - profiles[current_mode].misses++; - profiles[current_mode].bytes += i; - return result; -} - -# define strcmp profile_strcmp -#endif /* DEBUG_SYM */ - - -/*----------------------------------------------------------------------. -| Initialise the symbol table, by allocating the necessary storage, and | -| zeroing all the entries. | -`----------------------------------------------------------------------*/ - -/* Pointer to symbol table. */ -symbol **symtab; - -void -symtab_init (void) -{ - size_t i; - symbol **s; - - s = symtab = (symbol **) xnmalloc (hash_table_size, sizeof (symbol *)); - - for (i = 0; i < hash_table_size; i++) - s[i] = NULL; - -#ifdef DEBUG_SYM - { - int e = atexit(show_profile); - if (e != 0) - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: unable to show symtab profile")); - } -#endif /* DEBUG_SYM */ -} - -/*--------------------------------------------------. -| Return a hashvalue for a string, from GNU-emacs. | -`--------------------------------------------------*/ - -static size_t -hash (const char *s) -{ - register size_t val = 0; - - register const char *ptr = s; - register char ch; - - while ((ch = *ptr++) != '\0') - val = (val << 7) + (val >> (sizeof (val) * CHAR_BIT - 7)) + ch; - return val; -} - -/*--------------------------------------------. -| Free all storage associated with a symbol. | -`--------------------------------------------*/ - -void -free_symbol (symbol *sym) -{ - if (SYMBOL_PENDING_EXPANSIONS (sym) > 0) - SYMBOL_DELETED (sym) = true; - else - { - free (SYMBOL_NAME (sym)); - if (SYMBOL_TYPE (sym) == TOKEN_TEXT) - free (SYMBOL_TEXT (sym)); - free (sym); - } -} - -/*-------------------------------------------------------------------. -| Search in, and manipulation of the symbol table, are all done by | -| lookup_symbol (). It basically hashes NAME to a list in the | -| symbol table, and searches this list for the first occurrence of a | -| symbol with the name. | -| | -| The MODE parameter determines what lookup_symbol () will do. It | -| can either just do a lookup, do a lookup and insert if not | -| present, do an insertion even if the name is already in the list, | -| delete the first occurrence of the name on the list, or delete all | -| occurrences of the name on the list. | -`-------------------------------------------------------------------*/ - -symbol * -lookup_symbol (const char *name, symbol_lookup mode) -{ - size_t h; - int cmp = 1; - symbol *sym, *prev; - symbol **spp; - -#if DEBUG_SYM - current_mode = mode; - profiles[mode].entry++; -#endif /* DEBUG_SYM */ - - h = hash (name); - sym = symtab[h % hash_table_size]; - - for (prev = NULL; sym != NULL; prev = sym, sym = sym->next) - { - cmp = strcmp (SYMBOL_NAME (sym), name); - if (cmp >= 0) - break; - } - - /* If just searching, return status of search. */ - - if (mode == SYMBOL_LOOKUP) - return cmp == 0 ? sym : NULL; - - /* Symbol not found. */ - - spp = (prev != NULL) ? &prev->next : &symtab[h % hash_table_size]; - - switch (mode) - { - - case SYMBOL_INSERT: - - /* If the name was found in the table, check whether it is still in - use by a pending expansion. If so, replace the table element with - a new one; if not, just return the symbol. If not found, just - insert the name, and return the new symbol. */ - - if (cmp == 0 && sym != NULL) - { - if (SYMBOL_PENDING_EXPANSIONS (sym) > 0) - { - symbol *old = sym; - SYMBOL_DELETED (old) = true; - - sym = (symbol *) xmalloc (sizeof (symbol)); - SYMBOL_TYPE (sym) = TOKEN_VOID; - SYMBOL_TRACED (sym) = SYMBOL_TRACED (old); - SYMBOL_NAME (sym) = xstrdup (name); - SYMBOL_SHADOWED (sym) = false; - SYMBOL_MACRO_ARGS (sym) = false; - SYMBOL_BLIND_NO_ARGS (sym) = false; - SYMBOL_DELETED (sym) = false; - SYMBOL_PENDING_EXPANSIONS (sym) = 0; - - SYMBOL_NEXT (sym) = SYMBOL_NEXT (old); - SYMBOL_NEXT (old) = NULL; - (*spp) = sym; - } - return sym; - } - /* Fall through. */ - - case SYMBOL_PUSHDEF: - - /* Insert a name in the symbol table. If there is already a symbol - with the name, insert this in front of it, and mark the old - symbol as "shadowed". */ - - sym = (symbol *) xmalloc (sizeof (symbol)); - SYMBOL_TYPE (sym) = TOKEN_VOID; - SYMBOL_TRACED (sym) = false; - SYMBOL_NAME (sym) = xstrdup (name); - SYMBOL_SHADOWED (sym) = false; - SYMBOL_MACRO_ARGS (sym) = false; - SYMBOL_BLIND_NO_ARGS (sym) = false; - SYMBOL_DELETED (sym) = false; - SYMBOL_PENDING_EXPANSIONS (sym) = 0; - - SYMBOL_NEXT (sym) = *spp; - (*spp) = sym; - - if (mode == SYMBOL_PUSHDEF && cmp == 0) - { - SYMBOL_SHADOWED (SYMBOL_NEXT (sym)) = true; - SYMBOL_TRACED (sym) = SYMBOL_TRACED (SYMBOL_NEXT (sym)); - } - return sym; - - case SYMBOL_DELETE: - case SYMBOL_POPDEF: - - /* Delete occurrences of symbols with NAME. SYMBOL_DELETE kills - all definitions, SYMBOL_POPDEF kills only the first. - However, if the last instance of a symbol is marked for - tracing, reinsert a placeholder in the table. And if the - definition is still in use, let the caller free the memory - after it is done with the symbol. */ - - if (cmp != 0 || sym == NULL) - return NULL; - { - bool traced = false; - if (SYMBOL_NEXT (sym) != NULL - && SYMBOL_SHADOWED (SYMBOL_NEXT (sym)) - && mode == SYMBOL_POPDEF) - { - SYMBOL_SHADOWED (SYMBOL_NEXT (sym)) = false; - SYMBOL_TRACED (SYMBOL_NEXT (sym)) = SYMBOL_TRACED (sym); - } - else - traced = SYMBOL_TRACED (sym); - do - { - *spp = SYMBOL_NEXT (sym); - free_symbol (sym); - sym = *spp; - } - while (*spp != NULL && SYMBOL_SHADOWED (*spp) - && mode == SYMBOL_DELETE); - if (traced) - { - sym = (symbol *) xmalloc (sizeof (symbol)); - SYMBOL_TYPE (sym) = TOKEN_VOID; - SYMBOL_TRACED (sym) = true; - SYMBOL_NAME (sym) = xstrdup (name); - SYMBOL_SHADOWED (sym) = false; - SYMBOL_MACRO_ARGS (sym) = false; - SYMBOL_BLIND_NO_ARGS (sym) = false; - SYMBOL_DELETED (sym) = false; - SYMBOL_PENDING_EXPANSIONS (sym) = 0; - - SYMBOL_NEXT (sym) = *spp; - (*spp) = sym; - } - } - return NULL; - - default: - M4ERROR ((warning_status, 0, - "INTERNAL ERROR: invalid mode to symbol_lookup ()")); - abort (); - } -} - -/*-----------------------------------------------------------------. -| The following function is used for the cases where we want to do | -| something to each and every symbol in the table. The function | -| hack_all_symbols () traverses the symbol table, and calls a | -| specified function FUNC for each symbol in the table. FUNC is | -| called with a pointer to the symbol, and the DATA argument. | -| | -| FUNC may safely call lookup_symbol with mode SYMBOL_POPDEF or | -| SYMBOL_LOOKUP, but any other mode can break the iteration. | -`-----------------------------------------------------------------*/ - -void -hack_all_symbols (hack_symbol *func, void *data) -{ - size_t h; - symbol *sym; - symbol *next; - - for (h = 0; h < hash_table_size; h++) - { - /* We allow func to call SYMBOL_POPDEF, which can invalidate - sym, so we must grab the next element to traverse before - calling func. */ - for (sym = symtab[h]; sym != NULL; sym = next) - { - next = SYMBOL_NEXT (sym); - func (sym, data); - } - } -} - -#ifdef DEBUG_SYM - -static void symtab_print_list (int i); - -static void M4_GNUC_UNUSED -symtab_debug (void) -{ - token_data td; - const char *text; - symbol *s; - int delete; - static int i; - - while (next_token (&td) == TOKEN_WORD) - { - text = TOKEN_DATA_TEXT (&td); - if (*text == '_') - { - delete = 1; - text++; - } - else - delete = 0; - - s = lookup_symbol (text, SYMBOL_LOOKUP); - - if (s == NULL) - printf ("Name `%s' is unknown\n", text); - - if (delete) - (void) lookup_symbol (text, SYMBOL_DELETE); - else - (void) lookup_symbol (text, SYMBOL_INSERT); - } - symtab_print_list (i++); -} - -static void -symtab_print_list (int i) -{ - symbol *sym; - size_t h; - - printf ("Symbol dump #%d:\n", i); - for (h = 0; h < hash_table_size; h++) - for (sym = symtab[h]; sym != NULL; sym = sym->next) - printf ("\tname %s, bucket %lu, addr %p, next %p, " - "flags%s%s%s, pending %d\n", - SYMBOL_NAME (sym), - (unsigned long int) h, sym, SYMBOL_NEXT (sym), - SYMBOL_TRACED (sym) ? " traced" : "", - SYMBOL_SHADOWED (sym) ? " shadowed" : "", - SYMBOL_DELETED (sym) ? " deleted" : "", - SYMBOL_PENDING_EXPANSIONS (sym)); -} - -#endif /* DEBUG_SYM */