diff options
author | Jeff Bailey <jbailey@raspberryginger.com> | 2000-02-17 03:03:19 +0000 |
---|---|---|
committer | Jeff Bailey <jbailey@raspberryginger.com> | 2000-02-17 03:03:19 +0000 |
commit | bd11691d6520f7539e7ed2efdf75f266719e27e9 (patch) | |
tree | 13d3a4e534f6df846a128af52438769b9f51f09e | |
download | m4-bd11691d6520f7539e7ed2efdf75f266719e27e9.tar.gz |
Initial revision
669 files changed, 88215 insertions, 0 deletions
diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 00000000..75f8a27f --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,226 @@ +Notes on the GNU Translation Project +************************************ + + GNU is going international! The GNU Translation Project is a way to +get maintainers, translators, and users all together, so that GNU will +gradually become able to speak many languages. A few packages already +provide translations for their messages. + + If you found this `ABOUT-NLS' file inside a GNU distribution, you +may assume that the distributed package does use GNU `gettext' +internally, itself available at your nearest GNU archive site. But you +do *not* need to install GNU `gettext' prior to configuring, installing +or using this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work at translations should contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be +related to internationalization, you should tell about the version of +`gettext' which is used. The information can be found in the +`intl/VERSION' file, in internationalized packages. + +One advise in advance +===================== + + If you want to exploit the full power of internationalization, you +should configure it using + + ./configure --with-included-gettext + +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in +the operating system where this package is being installed. So far, no +prior implementation provides as many useful features (such as locale +alias or message inheritance). It is also not possible to offer this +additional functionality on top of a `catgets' implementation. Future +versions of GNU `gettext' will very likely convey even more +functionality. So it might be a good idea to change to GNU `gettext' +as soon as possible. + +INSTALL Matters +=============== + + Some GNU packages are "localizable" when properly installed; the +programs they contain can be made to speak your own native language. +Most such packages use GNU `gettext'. Other packages have their own +ways to internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system provides +usable `catgets' (if using this is selected by the installer) or +`gettext' functions. If neither is available, the GNU `gettext' own +library will be used. This library is wholly contained within this +package, usually in the `intl/' subdirectory, so prior installation of +the GNU `gettext' package is *not* required. Installers may use +special options at configuration time for changing the default +behaviour. The commands: + + ./configure --with-included-gettext + ./configure --with-catgets + ./configure --disable-nls + +will respectively bypass any pre-existing `catgets' or `gettext' to use +the internationalizing routines provided within this package, enable +the use of the `catgets' functions (if found on the locale system), or +else, *totally* disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl.a' file and +will decide to use this. This might be not what is desirable. You +should use the more recent version of the GNU `gettext' library. I.e. +if the file `intl/VERSION' shows that the library which comes with this +package is more recent, you should use + + ./configure --with-included-gettext + +to prevent auto-detection. + + By default the configuration process will not test for the `catgets' +function and therefore they will not be used. The reasons are already +given above: the emulation on top of `catgets' cannot provide all the +extensions provided by the GNU `gettext' library. If you nevertheless +want to use the `catgets' functions use + + ./configure --with-catgets + +to enable the test for `catgets' (this causes no harm if `catgets' is +not available on your system). If you really select this option we +would like to hear about the reasons because we cannot think of any +good one ourself. + + Internationalized packages have usually many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +Using This Package +================== + + As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +ISO 639 `LL' two-letter code prior to using the programs in the +package. For example, let's suppose that you speak German. At the +shell prompt, merely execute `setenv LANG de' (in `csh'), +`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This +can be done from your `.login' or `.profile' file, once and for all. + + An operating system might already offer message localization for +many of its programs, while other programs (whether GNU or not) have +been installed locally with the full capabilities of GNU `gettext'. +Just using `gettext' extended syntax for `LANG' would break proper +localization of already available operating system programs. In this +case, users should set both `LANGUAGE' and `LANG' variables in their +environment, as programs using GNU `gettext' give preference to +`LANGUAGE'. For example, some Swedish users would rather read +translations in German than English for when Swedish is not available. +This is easily accomplished by setting `LANGUAGE' to `sv:de' while +leaving `LANG' to `sv'. + +Translating Teams +================= + + For the GNU Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list, courtesy of Linux +International. You may reach your translation team at the address +`LL@li.org', replacing LL by the two-letter ISO 639 code for your +language. Language codes are *not* the same as the country codes given +in ISO 3166. The following translation teams exist, as of February +1997: + + Arabic `ar', Chinese `zh', Czech `cs', Danish `da', Dutch `nl', + English `en', Esperanto `eo', Finnish `fi', French `fr', German + `de', Greek `el', Hebrew `he', Hungarian `hu', Irish `ga', Italian + `it', Indonesian `id', Japanese `ja', Korean `ko', Latin `la', + Norwegian `no', Persian `fa', Polish `pl', Portuguese `pt', + Russian `ru', Slovenian `sl', Spanish `es', Swedish `sv', Telugu + `te', Turkish `tr' and Ukrainian `uk'. + +For example, you may reach the Chinese translation team by writing to +`zh@li.org'. + + If you'd like to volunteer to *work* at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is *not* the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +*actively* in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `gnu-translation@gnu.ai.mit.edu' to reach +the GNU coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology used in GNU. Proven linguistic skill are praised more +than programming skill, here. For the time being, please avoid +subscribing to the English team unless explicitly invited to do so. + +Available Packages +================== + + Languages are not equally supported in all GNU packages. The +following matrix shows the current state of GNU internationalization, +as of February 1997. The matrix shows, in regard of each package, for +which languages PO files have been submitted to translation +coordination. + + Ready PO files cs de en es fi fr ja ko nl no pl pt sl sv + .-------------------------------------------. + bash | [] [] [] | 3 + bison | [] [] [] | 3 + clisp | [] [] [] | 3 + cpio | [] [] [] [] [] | 5 + diffutils | [] [] [] [] | 4 + enscript | [] [] [] [] [] | 5 + fileutils | [] [] [] [] [] [] [] [] | 8 + findutils | [] [] [] [] [] [] [] | 7 + flex | [] [] [] | 3 + gcal | [] [] [] | 3 + gettext | [] [] [] [] [] [] [] [] [] [] | 11 + grep | [] [] [] [] [] [] [] [] | 8 + hello | [] [] [] [] [] [] [] [] [] [] | 10 + id-utils | [] [] | 2 + indent | [] [] | 2 + libc | [] [] [] [] [] [] [] | 7 + m4 | [] [] [] [] [] | 5 + make | [] [] [] [] [] [] | 6 + music | [] | 1 + ptx | [] [] [] [] [] [] [] [] | 8 + recode | [] [] [] [] [] [] [] [] | 8 + sh-utils | [] [] [] [] [] | 5 + sharutils | [] [] [] [] [] | 5 + tar | [] [] [] [] [] [] [] [] [] | 9 + texinfo | | 0 + textutils | [] [] [] [] [] [] | 6 + wdiff | [] [] [] [] [] [] [] [] | 8 + `-------------------------------------------' + 14 languages cs de en es fi fr ja ko nl no pl pt sl sv + 27 packages 1 22 1 14 1 25 1 10 20 7 14 7 7 15 145 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +GNU distribution. + + If February 1997 seems to be old, you may fetch a more recent copy +of this `ABOUT-NLS' file on most GNU archive sites. + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..93f8e657 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,20 @@ +Authors of GNU m4. + +The following contributions warranted legal paper exchanges with the +Free Software Foundation. Also see files ChangeLog and THANKS. + +M4 Rene Seindal (DENMARK, 1964) +Assigns the program. + +M4 University of Copenhagen +Disclaims the program. + +M4 James L. Avera (USA) 10/4/93 +Assigns changes to M4. +Changed (in m4-1.0.3): M4.c M4.h debug.c Makefile.in configure.in +Changelog +Added: stackovf.c tests/stackovf_test.sh + +M4 Pete Chown (UK, 1972) 6/28/94 +Assigns changes to M4 (builtin.c, input.c, m4.h, m4.texinfo, macro.c). + diff --git a/BACKLOG b/BACKLOG new file mode 100644 index 00000000..addae38e --- /dev/null +++ b/BACKLOG @@ -0,0 +1,51 @@ +# Summary of pending email for GNU m4 1.4. +# Last updated: Saturday, November 05, 1994. + +rmail/announce + 1. 15 Sep 94 <pinard@IRO.UMontreal.CA> Release: GNU m4 1.3 + 2. 29 Oct 94 <pinard@IRO.UMontreal.CA> Prerelease: GNU m4 1.3.1 + +rmail/changeword + 1. 02 Sep 94 <pinard> Re: Prerelease: GNU m4 1.2.3 + 2. 05 Sep 94 <Pete.Chown@dale.dircon.co.uk> Re: Prerelease: GNU m4 1.2.3 + +rmail/configuration + 1. 03 Nov 94 <Fredrik_Lundh@ivab.se> Re: m4 1.3 on DEC OSF/1 3.0 + 2. 05 Nov 94 <pinard> Re: m4 1.3 on DEC OSF/1 3.0 + +rmail/documentation + 1. 05 Jun 92 <berstel@mipsmath.math.uqam.ca> Re: M4 + 2. 10 Nov 92 <tchrist@convex.COM> Re: Is anyone using m4? + 3. 25 May 94 <schwab@issan.informatik.uni-dortmund.de> Autoconf 1.11: minor bu + 4. 27 Jul 94 <pinard@IRO.UMontreal.CA> Re: 0.95: Spacing details + 5. 28 Jul 94 <pinard@IRO.UMontreal.CA> Re: 0.95: Spacing details + 6. 31 Aug 94 <kb@cs.umb.edu> Re: Frozen file documentation to proofread + +rmail/floating-point + 1. 27 Oct 94 <johnm@vlibs.com> Re: enhancement to m4 eval() + 2. 25 Oct 94 <johnm@vlibs.com> enhancement to m4 + 3. 27 Oct 94 <pinard> Re: enhancement to m4 + 4. 27 Oct 94 <johnm@vlibs.com> Re: enhancement to m4 eval() + 5. 27 Oct 94 <pinard> Re: enhancement to m4 eval() + 6. 27 Oct 94 <johnm@vlibs.com> Re: enhancement to m4 eval() + 7. 28 Oct 94 <pinard> Re: enhancement to m4 eval() + 8. 28 Oct 94 <pinard> Re: enhancement to m4 eval() + 9. 28 Oct 94 <feeley@IRO.UMontreal.CA> Re: enhancement to m4 eval() +10. 28 Oct 94 <pinard> Re: enhancement to m4 eval() +11. 28 Oct 94 <johnm@vlibs.com> Re: enhancement to m4 eval() +12. 28 Oct 94 <johnm@vlibs.com> Re: enhancement to m4 eval() +13. 28 Oct 94 <pinard@IRO.UMontreal.CA> Re: enhancement to m4 eval() + +rmail/format-rewrite + 1. 25 Jun 94 <tmcconne@sedona.intel.com> Re: Prerelease: GNU m4 1.1.3 + +rmail/named-formals + 1. 30 Sep 94 <djm@va.pubnix.com> m4 macros with named formal parameters + +rmail/purify + 1. 06 Dec 93 <vern@horse.ee.lbl.gov> m4 1.1.1 "make realclean" + +rmail/speed + 1. 29 Aug 94 <pinard> Re: diversions and freezing + 2. 05 Sep 94 <djm@va.pubnix.com> slowness + 3. 04 Oct 94 <pinard> Autoconf, m4, and dnl's. diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 Library 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 + + Appendix: 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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. + + <signature of Ty Coon>, 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 Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..664472a5 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1526 @@ +Sat Nov 5 15:52:47 1994 Francois Pinard (pinard@icule) + + * Release 1.4. + + * doc/Makefile.in (realclean): Also remove stamp-vti. + Reported by Eric Backus. + +Wed Nov 2 00:47:53 1994 Francois Pinard (pinard@icule) + + * src/freeze.c (produce_frozen_state): If the frozen file cannot + be opened, return immediately after producing the error message. + Reported by Andreas Schwab. + + * configure.in: Check for const only after having found possible + ANSIfying compiler flags, this is of no use to check it before. + Reported by Alexander Lehmann. + +Tue Nov 1 22:02:37 1994 Francois Pinard (pinard@icule) + + * src/macro.c (collect_arguments): Cast obstack arguments to + (voidstar), so avoiding compiler warnings. + Reported by Joseph E. Sacco. + + * src/freeze.c (produce_frozen_state): Cast printed lengths to + (int) so they correspond to %d format items. + Reported by Joseph E. Sacco. + + * src/m4.c (main): Cast the argument to xfree to (voidstar). + * src/symtab.c (free_symbol): Idem. + Reported by Karl Vogel. + +Mon Oct 31 02:11:19 1994 Francois Pinard (pinard@icule) + + * Makefile.in (DISTFILES): Distribute BACKLOG. + + * configure.in: Define PRODUCT and VERSION. + * acconfig.h: Document PRODUCT and VERSION. + * src/m4.c, src/freeze.c: Use PRODUCT and VERSION instead of the + constant string m4 and variable or parameter named version. + +Sun Oct 30 08:13:03 1994 Francois Pinard (pinard@icule) + + * src/m4.h, src/debug.c: Replace all #ifdef __STDC__ by #if + __STDC__. Alliant FX/2800 Concentrix 2.2 (i860-BSD4.3) compiler + defines __STDC__ to 0, for indicating it is *not* ANSI! + Reported by Kaveh R. Ghazi. + + * configure.in: Added obsolescent tests for AIX and Minix. + + * doc/Makefile.in (mostlyclean): Remove texclean in dependencies, + which texclean does not exist anymore. + Reported by Eric Backus, Jim Meyering, John David Anglin and + Joseph E. Sacco. + +Sat Oct 29 05:10:03 1994 Francois Pinard (pinard@icule) + + * aclocal.m4 (fp_C_PROTOTYPES): Force -D_HPUX_SOURCE with -Aa. + Reported by John David Anglin. + + * src/ansi2knr.c: New version, sent by Peter Deutsch. + * aclocal.m4 (fp_C_PROTOTYPES): Substitute empty or ansi2knr for + ANSI2KNR, depending on the fact the compiler is ANSI or not. + * src/Makefile.in: Use -Ovarargs=convert on ansi2knr calls. + Remove the sed filter after ansi2knr for debug.c. Use $O instead + of $U, put underline in extensions rather than in basenames. Use + implicit rules, now that regularity makes this possible. + Have $(OBJECTS) depend on $(ANSI2KNR), so to trigger compilation + of ansi2knr whenever it is needed. + * configure.in: Adjusted for correct STACKOVF substitution. + * src/debug.c (trace_format): When not __STDC__, use (...) as a + parameter list, so ansi2knr will convert it to (va_alist) va_dcl. + Reported by David MacKenzie. + + * Makefile.in: Remove binprefix. Use transform_name instead. + Reported by David MacKenzie. + + * doc/Makefile.in: Create version.texi, use it, clean it. + Reported by Jim Meyering. + +Fri Oct 28 20:33:55 1994 Francois Pinard (pinard@icule) + + * Makefile.in (all, install, uninstall): Depend on Makefile. + + * Makefile.in: For actions invoking $(MAKE) from within compound + sh statements, exit non-zero if the sub-make fails. Otherwise, + the top-level make may exit successfully when it should fail. + Reported by Jim Kingdon. + + * {,/*}Makefile.in: Use && after all cd, in case they fail. + + * {,*/}Makefile.in: Declare PRODUCT and VERSION macros. + (dist): Use PRODUCT and VERSION instead of tricks on .fname. + * configure.in: Substitute PRODUCT and VERSION. + + * {,*/}Makefile.in (dist): Always try a hard link before a copy. + +Thu Oct 27 22:32:58 1994 Francois Pinard (pinard@icule) + + * Makefile.in (mostlyclean-local): Do not remove *~. + * */Makefile.in (mostlyclean): Idem. + Reported by Robert E. Brown and Richard Stallman. + +Sun Oct 9 08:30:13 1994 Francois Pinard (pinard@icule) + + * src/m4.h: Get rid of CONFIG_BROKETS. + +Sun Oct 2 16:48:10 1994 Francois Pinard (pinard@icule) + + * configure.in: Use AC_ARG_PROGRAM. + * aclocal.m4 (fp_C_PROTOTYPES): Substitute @kr@ by kr or empty. + Reported by David MacKenzie. + +Sat Oct 1 11:22:42 1994 Francois Pinard (pinard@icule) + + * configure.in: Do not add -O to CFLAGS for GNU C, now that + configure does it automatically. + Reported by Jim Meyering. + +Fri Sep 23 08:16:58 1994 Francois Pinard (pinard@icule) + + * src/stackovf.c: Declare the handler_t typedef earlier in the + code, use it for stackovf_handler. + (setup_stackovf_trap): Use RETSIGTYPE instead of void while + casting sigsegv_handler. + Reported by Robert Bernstein. + + * src/m4.c (main): Initialize program_name to argv[0] without + basename'ing it. + Reported by Karl Berry. + +Sun Sep 18 11:42:50 1994 Francois Pinard (pinard@icule) + + * src/Makefile.in (TAGS): Include a ../lib/TAGS reference. + Reported by Karl Berry. + +Wed Sep 14 10:00:22 1994 Francois Pinard (pinard@icule) + + * lib/Makefile.in (mostlyclean): Added. + (TAGS): Make in $(srcdir). + + * configure.in: Use `choke me' in test, like everywhere! + + * {doc,examples,lib,src}/Makefile.in (check): Deleted, as + unreacheable and useless. + + * doc/Makefile.in (texclean): Deleted, merged in mostlyclean. + + * lib/Makefile.in (DISTFILES): Distribute TAGS. + (distclean): Do not remove TAGS. + (realclean): Remove it. + * Makefile.in: Make TAGS in lib also, not just in src. + Reported by Karl Berry. + + * Makefile.in (distclean, realclean): Instead of recursively + calling $(MAKE) for the -local part, allow parallel execution of + -recursive and -local, only delay the removal of config.status, + which is repeated in both goals. + +Tue Sep 13 19:21:05 1994 Francois Pinard (pinard@icule) + + * Release 1.3. + + * Makefile.in: Group all *clean-recursive goals in one, using sed + to remove `-recursive' while calling make recursively. Also, use + a subshell for each recursive $(MAKE). + Reported by Jim Meyering. + + * src/m4.h (memcpy): Define with bcopy for BSD systems. + Reported by Kaveh R. Ghazi. + + * src/Makefile.in (ansi2knr): Use $(LIBS) while linking, for SunOS + 4.1.3 requires -ldl to link even ansik2nr, and we need a way to + specify it. + + * configure.in: Use date instead of touch for stamp-h. + * Makefile.in (stamp-h.in): Idem. + + * Makefile.in (distclean, realclean): Force serial execution of + both goals, in case parallel makes are being used. + Reported by Jim Meyering. + + * src/Makefile.in (DISTFILES): Distribute TAGS. + (distclean): Do not remove TAGS. + (realclean): Remove it. + Reported by Karl Berry. + +Sat Sep 10 12:34:04 1994 Francois Pinard (pinard@icule) + + * configure.in: Use fp_ to match aclocal.m4. Revert _OS_ macros + to old names, for following Autoconf. + +Thu Sep 8 15:07:27 1994 Francois Pinard (pinard@icule) + + * Makefile.in (MDEFINES): Remove INSTALL substitutions, for + ./install.sh will not be correctly referred to in sub-Makefiles. + Reported by John David Anglin. + + * doc/Makefile.in (texclean): Remove *.cps and *.fns too. + Reported by Eric Backus. + + * Makefile.in, checks/Makefile.in, doc/Makefile.in, + examples/Makefile.in, lib/Makefile.in, src/Makefile.in: Limit + config.status into remaking this directory's Makefile only. + * Makefile.in (stamp-h): Do not check nor touch stamp-h. + * configure.in (AC_OUTPUT): Touch stamp-h if CONFIG_HEADERS. + Reported by Jim Meyering. + +Tue Sep 6 12:07:33 1994 Francois Pinard (pinard@icule) + + * configure.in: Correct stack overflow detection logic, taking + care of systems having only incomplete implementations (like for + Pyramid 9820 OSx 5.0d). + Reported by Kaveh R. Ghazi. + + * src/Makefile.in (TAGS): Remote -t from etags call. + +Fri Sep 2 10:37:10 1994 Francois Pinard (pinard@icule) + + * lib/Makefile.in (install): Depend on all. + +Wed Aug 31 11:17:21 1994 Francois Pinard (pinard@icule) + + * examples/Makefile.in (mostlyclean): Do not depend on texclean. + Reported by Jim Meyering and John David Anglin. + + * Makefile.in (distclean-local): Delete config.log. + Reported by Jim Meyering. + + Solidify frozen files with respect to -P: + * src/m4.c: Have -P set prefix_all_buitins variable instead of + calling a function by that name. Declare the variable. + * src/m4.h: Adjust declaration for prefix_all_buitins. + * src/builtin.c (builtin_init): Merge in functionality from + previous prefix_all_buitins function, while making entries in the + symbol table, but not modifying the builtin description itself. + + * src/freeze.c (reload_frozen_state): Add a useless `break;', + because *many* compilers do not accept an empty `default:'. + Reported by Akiko Matsushita, Eric Backus, John David Anglin, + Joseph E. Sacco, Kaveh R. Ghazi, Tom McConnell and Ulrich Drepper. + + * configure.in: Use AC_TYPE_SIGNAL. + * src/stackovf.c (setup_stackovf_trap): Use RETSIGTYPE. + Reported by Robert Bernstein. + + * checks/Makefile.in (check): Modify PATH so check-them will find + m4 in the src directory. + * Makefile.in (check): Don't. + Reported by Akiko Matsushita and Jim Meyering. + + * src/output.c (make_room_for, output_character_helper): New + functions, for implementing a global MAXIMUM_TOTAL_SIZE instead of + a per buffer MAXIMUM_BUFFER_SIZE. + + * src/output.c (output_text): New function, for optimizing the + output of strings of characters. Use it. + +Tue Aug 30 01:44:29 1994 Francois Pinard (pinard@icule) + + * doc, src: New directories reorganizing the distribution. + * doc/Makefile.in, src/Makefile.in, examples/Makefile.in: New + files. + * Makefile.in: Adjusted. + * configure.in: Configure new Makefiles. + + * m4.h: Declare STRING typedef. Use it for comment and quote + strings, adjusting all references. (This is the rudiments of a + beginning for the eventual withdrawal of NUL terminated strings.) + * output.c (shipout_text): Accept a length parameter, and use it. + All callers adjusted. + +Mon Aug 29 12:27:19 1994 Francois Pinard (pinard@icule) + + * m4.h: Include <unistd.h> if it exists. + * stackovf.c: Don't. + + Clean up for current_diversion variable: + * output.c: Move current_diversion from builtin.c. + * m4.h: Declare current_diversion so builtin.c can access it. + * output.c (output_init, make_diversion): Initialize or update + current_diversion. + * builtin.c (builtin_init, m4_divert): Leave current_diversion + alone. + + Remove limit on number of diversions: + * output.c: Replace ndiversion by diversions, declare it. + (output_init): Allocate only diversion 0. + (make_diversion): Allocate new diversions as needed. + * m4.h, m4.c: Remove NDIVERSIONS and ndiversion related stuff. + * m4.c: Still accept -N, but do nothing with it. + Reported by David MacKenzie. + + Freeze diversions: + * output.c (freeze_diversions): New function. + * m4.h: Declare freeze_diversions. + * freeze.c: Document frozen file format, revise it, call + freeze_diversions to add diversions to frozen format, and code to + reload them properly. + * m4.c: Do not undivert automatically at end when status being + frozen. Do not call builtin_init when reloading frozen state. + + Speed up diversion processing: + * output.c: Add INITIAL_BUFFER_SIZE, MAXIMUM_BUFFER_SIZE, + COPY_BUFFER_SIZE, in-memory diversion buffers, struct diversion + structure and variables, cached variables out of output_diversion, + reallocate_diversion_for and OUTPUT_CHARACTER. + (shipout_text, make_diversion, insert_diversion): Adapted to new + structures. + (insert_file): Use better buffering. + Reported by David MacKenzie. + +Sun Aug 28 05:20:02 1994 Francois Pinard (pinard@icule) + + * Makefile.in, lib/Makefile.in, checks/Makefile.in: Arrange so + dist works from another build directory. + +Sat Aug 27 14:32:45 1994 Francois Pinard (pinard@icule) + + * symtab.c (hack_all_symbols): Use hash_table_size instead of + constant HASHMAX, for -H option to work better. + + * builtin.c (DECLARE): Simplify by using _ (). + + * freeze.c: New file. + * Makefile.in: Compile it, distribute it. + * m4.c: Recognize, document and process --freeze-state (-F) and + --reload-state (-R) options. Pass a true flag to builtin_init + only if no reloading some state. + * builtin.c (define_builtin): Remove static specifier. + (find_builtin_by_name): Remove static specifier. + (builtin_init): Accept and obey a flag argument. + * m4.h: Add declarations for freeze.c, changes for builtin.c. + +Wed Aug 24 16:14:19 1994 Francois Pinard (pinard@icule) + + * builtin.c (dumpdef_cmp): Rewrite so the cast protect the const + specifier. + + * configure.in: Implement --with-dmalloc. + * acconfig.h: Document WITH_DMALLOC. + * m4.h: Add code for when WITH_DMALLOC. + +Mon Aug 15 12:38:05 1994 Francois Pinard (pinard@icule) + + * m4.c (long_options): Use "error-output", the dash was missing. + Reported by Akiko Matsushita. + +Fri Aug 12 16:38:01 1994 Francois Pinard (pinard@icule) + + * m4.h: Include <sys/types.h>. + * builtin.c, debug.c, m4.c, output.c, stackovf.c: Don't. + * m4.h: Declare len_lquote and len_rquote as size_t, not int. + int. + * input.c: Declare len_lquote, len_rquote, len_bcomm and len_ecomm + as size_t, not int. + * builtin.c (dump_args): Declare len as size_t, not int. + + * debug.c: Prototype the forward declaration of debug_set_file. + + * builtin.c (m4_undivert): Replace div by file, for avoiding the + shadowing of this variable. + * output.c (insert_diversion): Idem. + + * input.c: Delete def_rquote, def_lquote, def_bcomm and def_ecomm. + (input_init): Duplicate default quote and comment strings. + (set_quotes): Free previous quote strings in all cases. Duplicate + even default quote strings. + (set_comment): Free previous comment strings in all cases. + Duplicate even default comment strings. + + * configure.in: Updated for Autoconf 2.0. + * Makefile.in (distclean-local): Also delete config.cache. + + * m4.c (usage): Reorganize the --help output by topic. Include a + description for debugging flags. + +Fri Jul 29 10:15:52 1994 Francois Pinard (pinard@icule) + + * configure.in: If sigaction is available and SA_ONSTACK defined, + use sigaction. Otherwise, if sigvec is available and SV_ONSTACK + defined, use sigvec. Else don't compile stackovf.c. + * stackovf.c (setup_stackovf_trap): Idem. + Reported by Jim Avera, Karl Berry, Kaveh R. Ghazi, Matthias Rabe + and Simon Leinen. + +Thu Jul 21 22:43:17 1994 Francois Pinard (pinard@icule) + + * m4.c (usage): Replace printf par fputs. + +Mon Jul 18 23:48:23 1994 Francois Pinard (pinard@icule) + + * Release 1.2 + +Sun Jul 17 08:08:25 1994 Francois Pinard (pinard@icule) + + * configure.in: Check for sigaction and sigvec. Add a new delayed + check for RLIMIT_STACK, combine in the checking for getrlimit. + All those things are not universally available. + * stackovf.c: Split setting up the trap handler and catching + signals, for better taking care of various configure outcomes. + * examples/stackovf.sh: Correct a typo. + Reported by Eric Backus, Jim Avera and Jim Meyering. + +Sat Jul 16 20:36:19 1994 Francois Pinard (pinard@icule) + + * ansi2knr.c: New version sent by its author, Peter Deutsch. + +Fri Jul 15 14:36:21 1994 Francois Pinard (pinard@icule) + + * Makefile.in: Modify so parallel make will not try making + lib/libm4.a twice simultaneously. + Reported by Jim Meyering. + +Thu Jul 14 17:23:17 1994 Francois Pinard (pinard@icule) + + * stackovf.c (setup_stackovf_trap): Replace "Don't" by "Do not" in + error message, for when no code possibility exists. Even if this + line is completely #ifdef'ed out, it brings a syntax error. + Reported by Andreas Schwab, Jim Meyering and Joseph E. Sacco. + + * Makefile.in (install): Have install depend on all too, for lib + to be remade as needed. + + * examples/stackovf.sh: Try ksh, bsh and bash for shells + providing ulimit, instead of using only ksh. + Reported by Jim Avera and Joseph E. Sacco. + +Tue Jul 12 06:54:31 1994 Francois Pinard (pinard@icule) + + * Makefile.in (check): Have it depend on all instead of m4. In + this way, a change in lib will be detected and processed. + + * builtin.c (numeric_arg): Use strtol and verify the conversion, + instead of using sscanf which stops as soon as there is a + non-digit in the input. Previously, incr(1xyzzy), eval(1,2xyzzy) + and divert(1xyzzy) were all accepted without any warning or error + messages. + * m4.h: Declare strtol as long if not including stdlib.h. + * configure.in: Check for limits.h, and replace strtol if missing. + * lib/Makefile.in: Substitute LIBOBJS. Distribute strtol.c. + * lib/strtol.c: New file, from elsewhere. + Reported by Andreas Schwab. + +Thu Jul 7 22:38:10 1994 Francois Pinard (pinard@icule) + + * macro.c (expand_macro): Cast value to (boolean) prior to + assigning it to traced. + Reported by Tom McConnell. + + * Makefile.in (m4): Always make all in lib first. + Reported by Jim Meyering. + +Wed Jul 6 13:16:31 1994 Jim Avera (jima@netcom.com) + + * stackovf.c: Isolated OS-dependent sections; Improved portability, + adding support for SunOS/BSD (sigvec, sigstack, and 4-parameter signal + handlers), and a default error message if the fault address is not + available (when neither siginfo.h nor BSD sigcontext are supported). + * configure.in: Changes for stackovf.h: Check for sigcontext, + sigaction, sigstack, and define rlim_t as int if necessary. + * acconfig.h: Added HAVE_SIGCONTEXT and rlim_t. + * examples/stackovf.sh: Run m4 -L99999999 to allow stack overflow. + * ansi2knr.c: Fix for func-ptr args; convert "..." to varargs syntax. + +Tue Jul 5 19:13:54 1994 Francois Pinard (pinard@icule) + + * configure.in: Use AC_SET_MAKE. + * Makefile.in: Use @SET_MAKE@. + Reported by Jim Meyering. + + * checks/check-them: Do not trap on SIGQUIT or SIGALRM. + Reported by Ian Taylor. + +Sat Jul 2 00:58:47 1994 Francois Pinard (pinard@icule) + + * configure.in: Remove dependency of USE_STACKOVF on STDC_HEADERS, + because siginfo.h is unrelated to standard headers, and siginfo.h + is already checked for. + Reported by Joseph E. Sacco. + + * acconfig.h, aclocal.m4, m4.h: Replace HAVE_PROTOTYPES by + PROTOTYPES. + * aclocal.m4, configure.in: Replace AC_HAVE_PROTOTYPES by + AC_PROTOTYPES. + +Wed Jun 29 22:41:53 1994 Francois Pinard (pinard@icule) + + * builtin.c (substitute): Use \& to represent this part of the + string which was matched by the whole regexp, instead of + representing the whole string. Any usage of \0 issues a warning + and acts like \&, it will disappear in some subsequent release. + +Mon Jun 27 14:24:23 1994 Francois Pinard (pinard@icule) + + * m4.c: Complete prototype for forwarded declaration of usage. + + * input.c (init_macro_token): Correct own reference in error + message. Previous name get_macro_func was referred to instead. + (next_char): Correct own reference in error message. Previous + name advance_input was referred to instead. + + * m4.h: Declare eval_t and unsigned_eval_t typedefs to 32 bits. + * eval.c (logical_or_term, logical_and_term, or_term, xor_term, + and_term, not_term, logical_not_term, cmp_term, shift_term, + add_term, mult_term, exp_term, unary_term, simple_term): Add + prototype to forwarded declarations. Declare parameter v1 as + eval_t * instead of int *. Same for local variable v2 in dyadic + functions. Same for result in exp_term. + * builtin.c (m4_eval): Declare value as eval_t instead of int. + (ntoa): Declare value as eval_t instead of int. Declare uvalue as + unsigned_eval_t instead of unsigned int. Change casts accordingly. + (shipout_int): Cast first argument of ntoa to eval_t. + Reported by Thorsten Ohl. + + * macro.c: Complete the prototypes of forwarded expand_macro and + expand_token. + Reported by Thorsten Ohl. + + * m4.h: Define voidstar as void * or char * depending on __STDC__. + The Ultrix 3.1 compiler cannot do much with void pointers. + + * builtin.c (dumpdef_cmp): Replace void * by voidstar. + * m4.c (xfree): Replace void * by voidstar. + Reported by Tom McConnell. + + * ansi2knr.1: New, from elsewhere. + * Makefile.in (DISTFILES): Distribute ansi2knr.1 + + * Makefile.in (stamp-h.in): Avoid running ./config.status if + stamp-h does not exist yet. This avoids running it a second time + just after the initial ./configure. + Reported by David MacKenzie and Tom McConnell. + + * m4.h: Replace the enum debug_info declaration with a series of + #define's. The Ultrix 3.1 compiler would otherwise need casting + (int) to most references, when used in expressions. + Reported by Tom McConnell. + +Sat Jun 25 00:10:05 1994 Francois Pinard (pinard@icule) + + * aclocal.m4: Replace FP_PROTOTYPES by AC_HAVE_PROTOTYPES, + following an idea from Brook G. Milligan. AC_HAVE_PROTOTYPES + calls the compiler. Previously, FP_PROTOTYPES was only calling + the preprocessor; by not being subject to CFLAGS, this was + discouraging those flags asking for ANSI compilation. + * acconfig.h: Document HAVE_PROTOTYPES. + * configure.in: Use AC_HAVE_PROTOTYPES instead of FP_PROTOTYPES. + * m4.h: Define _() according to HAVE_PROTOTYPES, not __STDC__. + Reported by Eric Backus. + + * configure.in: Substitute CFLAGS and LDFLAGS, taking their value + from the environment. Default CFLAGS to -g if not set. + * Makefile.in: Have CFLAGS and LDFLAGS substituted from configure. + * lib/Makefile.in: Have CFLAGS substituted from configure. + Reported by Eric Backus and Tom McConnell. + + * configure.in: m4_undefine changeword before using AC_ENABLE. + + * m4.h: Declare prototypes for error (for ANSI compilers only), + prefix_all_builtins and reference_error. + Reported by Tom McConnell. + + * input.c (set_word_regexp): Do not try to initialize the array + test from a string, this does not work with non-ANSI compilers. + Reported by Eric Backus. + + * Makefile.in (dist): Clean examples/ before saving it. + (distclean-local): Also remove stamp-h. + Reported by Eric Backus. + + * Makefile.in (_stackovf.c): Goal for compiling stacokovf.c with + non ANSI compilers. + Reported by Tom McConnell. + + * checks/Makefile.in (clean): Depends on mostlyclean. + (mostlyclean): New goal. + +Fri Jun 24 23:30:31 1994 Francois Pinard (pinard@icule) + + * Makefile.in (DISTFILES): Distribute install.sh. + * install.sh: New file, copied from elsewhere. + Reported by Assar Westerlund and Kaveh R. Ghazi. + +Thu Jun 23 00:00:30 1994 Francois Pinard (pinard@icule) + + * configure.in: Define ENABLE_CHANGEWORD if --enable-changeword. + * acconfig.h: Explain ENABLE_CHANGEWORD. + + [These modifs all depend upon ENABLE_CHANGEWORD and are adapted + from code provided by Pete Chown] + * m4.h: Add original_text field to u_t variant of union u. + Declare TOKEN_DATA_FUNC macro. + * builtin.c: Declare changeword. + (m4_changeword): New function. + * input.c: Include "regex.h", define variables with word regexps. + (input_init): Initialize the word regexp. + (set_word_regexp): New. + (next_token): Declare local variables, use the previous code if + default_word_regexp is true. Else, match using a new code. Save + the original text. + * macro.c (expand_token): Ship out original text if not a macro + name. + Reported by Krste Asanovic and Pete Chown. + + [These modifs all depend upon ENABLE_CHANGEWORD] + * m4.h: Declare external user_word_regexp. + * m4.c: Declare user_word_regexp, and initialize it from + --word-regexp or -W, or NULL if not specified. + * input.c: Use user_word_regexp if specified, instead of + DEFAULT_WORD_REGEXP. + + * Makefile.in (m4): Revert Jan 3 1994 change. I'm unable to + agree with it. + + * Makefile.in, lib/Makefile.in: Limit suffixes to .c and .o. + * checks/Makefile.in: Empty the suffix list. + Reported by Geoff Russell, Joel Sherrill and Roland McGrath. + + * m4.c: Declare nesting_limit and initialize it to 250. + Implement -LNUMBER or --nesting-limit=NUMBER to change its + value. + * m4.h: Declare nesting_limit as external. + * macro.c (expand_macro): Stop execution whenever nesting limit + is exceeded. + Reported by Bengt Mertensson. + + * eval.c (evaluate): Diagnose excess characters in eval input. + Things like `eval(08)' used to return 0 with no diagnostic. + + * m4.h: Capitalize first letter of all macro arguments in + definitions. + + * m4.c: Declare warning_status, initialize it to 0. Add new + option -E, or --fatal-warnings, which sets warning_status to + EXIT_FAILURE instead. + * m4.h: Declare external warning_status. Define EXIT_SUCCESS and + EXIT_FAILURE if not otherwise done by header files. + * m4.c: Delete declarations for EXIT_SUCCESS and EXIT_FAILURE. + * m4.c, input.c, output.c, symtab.c, builtin.c, macro.c, debug.c, + eval.c: Replace 0 by warning_status and 1 by EXIT_FAILURE in first + argument of all M4ERROR calls. + Reported by Noah Friedman. + + * examples/incl-test.m4: Renamed from incl_test.m4. + * examples/include.m4: Include incl-test.m4 instead of + incl_test.m4. + * examples/multiquotes.m4: Renamed from multi-quotes.m. + +Wed Jun 22 21:58:54 1994 Francois Pinard (pinard@icule) + + * configure.in: Avoid USE_STACKOVF if <siginfo.h> not found. Note + that Jim developped stackovf.c on a 486 running SVR4.0 (ESIX), and + also tested it on a Sun Sparc workstation running SunOS 4.x. + + * format.c (format): When not HAVE_EFGCVT, m4 was failing the + 49.format check, abusing a `union values' argument with sprintf + without selecting the proper field. Now, save the formatting type + first, delaying the fetch of the corresponding argument. + Reported by Joseph E. Sacco and Tom Quinn. + + * format.c (format): Remove const from char *fmt declaration when + not HAVE_EFGCVT, because a NUL may be forced into it. + + * m4.h: Declare atof() when not STDC_HEADERS. + Reported by Joseph E. Sacco. + + * Regenerate configure using Autoconf 1.11, this corrects a + problem about an incorrect cpp seting on NeXT 3.1. + Reported by Alexander Lehmann. + +Sun Jun 5 16:25:19 1994 Francois Pinard (pinard@icule) + + * m4.h (_): Change argument from `x' to `Args'. + +Wed May 4 23:59:39 1994 Francois Pinard (pinard@icule) + + * Makefile.in: Remove all occurrences of $(MFLAGS), which were + bringing more evil than good on a few systems. + Reported by Greg A. Woods. + +Fri Apr 22 15:59:35 1994 Francois Pinard (pinard@icule) + + * m4.h: Rename Args() to _(). + * m4.h: Remove extern specifier from all function declarations. + +Fri Apr 22 15:51:21 1994 Jim Avera (jima@netcom.com) + + * stackovf.c: New file implementing stack-overflow detection. + * configure.in: Check for getrlimit, sigaction. If all of + standard headers, getrlimit and sigaction, define USE_STACKOVF and + substitute ${U}stackovf.o for STACKOVF. + * acconfig.h: Declare USE_STACKOVF. + * Makefile.in: Distribute stackovf.c, link with $(STACKOVF). + * m4.h: Declare setup_stackovf_trap(). + * m4.c: Call setup_stackovf_trap(). + * tests/stackovf_test.sh: New file. + +Wed Apr 13 14:10:30 1994 Francois Pinard (pinard@icule) + + * checks/Makefile.in: Rename .all-stamp to stamp-checks. + + * Makefile.in (Makefile, etc.): Adapt for Autoconf 1.8. + +Sun Jan 30 14:24:19 1994 (pinard at icule) + + * m4.h: Remove definition of volatile, not used anymore. + Reported by Jim Meyering and Joseph E. Sacco. + + * m4.h: Consistently use `do { ... } while (0)' in macros, instead + of `if ... else /* nothing */' for if macros. + Reported by Jim Meyering. + + * builtin.c (m4_regexp): Reorganize the code for avoiding a + warning from gcc about `repl' possibly used before defined. + Reported by Jim Meyering. + + * m4.h: Avoid a pre-ANSI <memory.h> together with <string.h>. + Reported by Jim Meyering. + +Tue Jan 25 18:39:37 1994 Francois Pinard (pinard at icule) + + * m4.h: Move the conditional definition of volatile after the + inclusion of system files, because they may define it first. + +Tue Jan 4 19:46:50 1994 Francois Pinard (pinard@icule) + + * checks/Makefile.in (CHECKS): Add a useless `*' before `[', to + get around a problem with Alpha make seeing a syntax error, there. + Reported by Vern Paxson. + +Mon Jan 3 00:21:45 1994 Francois Pinard (pinard@icule) + + * Makefile.in: Do not define LDFLAGS, use CFLAGS on link calls. + Reported by Richard Stallman. + +Sat Dec 25 08:06:05 1993 Francois Pinard (pinard@icule) + + * configure.in: Correct test for strerror, AC_FUNC_CHECK was used + instead of AC_HAVE_FUNCS. + Reported by Noah Friedman. + +Wed Dec 1 09:37:53 1993 Francois Pinard (pinard@icule) + + * m4.c: Initialize show_help and show_version to zero. + + * m4.c: Ensure EXIT_SUCCESS and EXIT_FAILURE are defined. + Use them in exit() and usage() calls. + +Sat Nov 27 10:43:24 1993 Francois Pinard (pinard@icule) + + * m4.h: Delete extern sys_nerr, sys_errlist declarations, and + syserr() macro. Delete errref, add reference_error and M4ERROR. + * m4.c: Replace errref, which was returning an input reference + string, with reference_error, which prints it on standard error. + * builtin.c, output.c: Use errno as second parameter to error, + instead of using syserr() with %s. + * *.c: Use M4ERROR instead of error: no more errref() with %s. + Doing so, the program name appears after the input reference + instead of before, which eases M-x next-error processing. + +Wed Nov 24 22:16:15 1993 Francois Pinard (pinard@icule) + + * checks/get-them: Escape braces with backslashes in patterns, + because HPUX-9.01 awk needs this. + Reported by Jim Meyering. + +Mon Nov 22 10:55:52 1993 Francois Pinard (pinard@icule) + + * builtin.c: Declare "FILE *popen ();". + + * m4.h: Remove MESSAGE{,1,2}, WARNING1, FATAL{,1}, INTERNAL_ERROR + macros, replace error_message_prefix() declaration by errref()'s. + Declare xrealloc, for use in errref(). + * m4.c: Delete error_message_prefix() function, add errref(). + * *.c: Use error() systematically in place of all error macros, + now that error() flushes stdout first. Make needed adjustments. + + * m4.h: Remove const in sys_errlist[] declaration, it creates + conflicts on SGI and Alpha. + Reported by Kaveh R. Ghazi. + +Sat Nov 20 08:26:15 1993 Francois Pinard (pinard@icule) + + * m4.c: Include <getopt.h> instead of "getopt.h". + + * configure.in: Output to config.h. Use HAVE_FUNCS preferably. + * acconfig.h: New, for documenting HAVE_EFGCVT. + * Makefile.in: Distribute acconfig.h, .stamp-h.in and config.h.in, + use them wherever appropriate. Also use -I. for compilations. + * lib/Makefile.in: Use -I.. for compilations. + * *.c: Include <config.h> or "config.h". + + * m4.h: Test for HAVE_MEMORY_H instead of NEED_MEMORY_H. + * configure.in: Use AC_HAVE_HEADERS(memory.h), delete AC_MEMORY_H. + +Wed Nov 17 09:34:55 1993 Francois Pinard (pinard@icule) + + * builtin.c (m4_eval): Cast strlen to (int) before comparing. + + * input.c (input_init): Initialize quote and comment strings + explicitely instead of calling set_quotes and set_comment: by + doing so, we ensure we do not free uninitialized variables. + + * checks/check-them: Reverse arguments to both diff, so the + expected is on the left and the obtained on the right. + + * m4.h: Add MESSAGE{,1,2}, WARNING1, FATAL{,1} and INTERNAL_ERROR + macros. Delete declarations for m4error, warning, fatal and + internal_error, add declaration for error_message_prefix. + * m4.c: Delete m4error, warning, fatal and internal_error + routines, add error_message_prefix routine. + * *.c: Replace m4error routine calls with MESSAGE* macro calls, + warning with WARNING*, fatal with FATAL* and internal_error with + INTERNAL_ERROR*. + * Makefile.in (_m4.c): Do not adjust ansi2knr output for va_alist, + this is not needed anymore. + + * m4.h: Declare extern FILE *debug. Add DEBUG_PRINT{1,3} and + DEBUG_MESSAGE{,1,2} macros. Delete declarations for debug_print + and debug_message, add declaration for debug_message_prefix. + * debug.c: Remove static specifier for FILE *debug declaration. + Delete debug_print and debug_message routines, add + debug_message_prefix routine. + * builtin.c, debug.c: Replace debug_print routine calls with + DEBUG_PRINT* macro calls. + * input.c, path.c: Replace debug_message routine calls with + DEBUG_MESSAGE* macro calls. + + * m4.h: Remove inclusion of <varargs.h>. + * debug.c: Include <stdarg.h> or <varargs.h>. + (trace_format): Use stdarg instead of varargs if __STDC__. + + * configure.in: Remove checks for vfprintf and _doprnt. These + implementations use varargs tricks which are not portable enough. + * lib/vfprintf.c: Deleted. + * lib/_doprnt.c: Deleted. + * lib/Makefile.in: Adjusted accordingly. Remove LIBOBJS. + Reported by Joel Sherrill. + + * path.c (add_include_directory): Use xstrdup. + + * builtin.c (find_builtin_by_name): Declare static. + + * *.[ch]: Add const to a few "char *" declarations. + + * configure.in: Remove commented tests for fileno() and fstat(). + * debug.c: Remove comments about HAVE_FILENO and HAVE_FSTAT. + + * debug.c (debug_flush_files): New. + * m4.h: Declares it. + * builtin.c (m4_syscmd, m4_esyscmd): Use it. + Reported by Nicolas Pioch. + +Fri Nov 12 10:02:26 1993 Francois Pinard (pinard@icule) + + * Makefile.in (m4.dvi): Use m4.texinfo instead of m4.texi. + Reported by Joel Sherrill. + + * builtin.c (prefix_all_builtins): Instead of the table size, use + the null entry at end for stopping the loop. It was overwritten. + Reported by Andreas Schwab and Jim Meyering. + + * builtin.c (prefix_all_builtins): Cast xmalloc to (char *). + Reported by Kaveh R. Ghazi. + + * macro.c (call_macro): Add * in (*SYMBOL_FUNC (sym)) (...). + Reported by Karl Vogel. + +Tue Nov 9 09:31:47 1993 Francois Pinard (pinard@icule) + + * m4.h: Do not define volatile if already defined. + Reported by Rene' Seindal. + + * lib/Makefile.in: Add a forgotten ALLOCA=@ALLOCA@. Grrr! + + Reported by Bernhard Daeubler, Eric Backus, Hal Peterson, Hoang + Uong, Ian Taylor, Kaveh R. Ghazi, Tom McConnell and Walter Wong. + +Mon Nov 8 21:11:44 1993 Francois Pinard (pinard@icule) + + * m4.h: Define strchr and strrchr in terms of index and rindex, + instead of the other way around. + * builtin.c, m4.c, path.c: Use strchr instead of index. + + * input.c (next_char): Remove a "break;" after a "return ...;". + Reported by Tom McConnell. + +Mon Nov 8 12:45:34 1993 Francois Pinard (pinard@icule) + + * Release 1.1 + + * configure.in: Do not copy check files in the build hierarchy. + * checks/check-them: Identify the m4 version being checked. For + finding m4, look in $PATH instead of in the parent directory. + * Makefile.in (check): Prepend `pwd` to $PATH before checking. + * checks/Makefile.in (.all-stamp): Always create check files in + the source hierarchy, not anymore in the build hierarchy. + (check): cd to the source hierarchy before performing checks. + Do not copy nor clean COPYING anymore, take it from `..'. + Reported by Tom McConnell. + + * Makefile.in (Makefile): Use $(SHELL). + (config.status): Use $(SHELL). Use "config.status --recheck" + instead of "configure --no-create", which is obsolete. + Reported by Tom McConnell. + +Fri Nov 5 09:49:30 1993 Francois Pinard (pinard@compy.IRO.UMontreal.CA) + + * m4.c (usage): Use "%s" instead of "m4" in format string. + Reported by Jim Meyering. + + * Makefile.in: Distribute mkinstalldirs. + Reported by Pierre Gaumond. + Reported by Jim Meyering. + Reported by Tom McConnell. + Reported by Andreas Gustafsson. + + * checks/check-them: Renamed from checks/check_them. + * checks/get-them: Renamed from checks/get_them. + * checks/.all-stamp: Renamed from checks/.all_stamp. + * checks/Makefile.in: Changed accordingly. + Reported by Jim Meyering. + +Thu Nov 4 13:50:52 1993 Francois Pinard (pinard@lagrande.IRO.UMontreal.CA) + + * lib/Makefile.in (dist): Correct permissions on files. + + * output.c: Declare tmpfile, some systems don't. + +Wed Nov 3 09:09:16 1993 Francois Pinard (pinard@icule) + + * checks/Makefile.in (dist): Correct permissions on files. + + * Makefile.in (dist): Ensure recursive linking for subdirectory + `examples', also set read/write permissions on all its files. + + * mkinstalldirs: New, from elsewhere. + * Makefile.in: Use it. + + * debug.c: Synchronize debug messages and regular output when + the debug file and stdout are redirected to the same file. + * configure.in: Add (commented) checks for fileno and fstat. + Reported by Jim Avera. + + * builtin.c (m4_ifelse): Diagnose excess arguments if 5, 8, 11, + etc., arguments, then ignore the superfluous one. m4 used to + diagnose missing arguments and return the empty string. + Reported by Nick S. Kanakakorn. + +Tue Nov 2 00:55:41 1993 Francois Pinard (pinard@icule) + + * m4.c (main): At end of all input, ensure all undiverted text + goes to the main output stream. + Reported by Andreas Gustafsson. + + * m4.c (main): exit (0), instead of return 0. + + * m4.c: Implement -P and --prefix-builtins. + * builtin.c: Delete const specifier on builtin_tab. + (prefix_all_builtins): New. + Reported by Noah Friedman. + Reported by Scott Bartram. + + * c-boxes.el: New, from elsewhere. + * Makefile.in: Distribute it. + + * m4.h: Do not define bcopy if <string.h> defines it. + Reported by Stephen Perkins. + + * builtin.c (define_macro): Allow a missing second argument, in + which case it is implied empty. Affects define and pushdef. + Reported by Eric Allman. + +Mon Nov 1 07:45:24 1993 Francois Pinard (pinard@icule) + + * m4.h: Add blind_if_no_args in struct builtin, blind_no_args in + struct symbol adn SYMBOL_BLIND_NO_ARGS macro. + * builtin.c: Initialize all the blindness fields in builtin_tab. + (define_builtin): Copy the blindness of a builtin into its symbol. + * macro.c (expand_token): Avoid processing a blind builtin if the + next character is not an opening parenthesis. + Reported by David MacKenzie. + Reported by Noah Friedman. + + * configure.in: Ensure an exit status of 0 on completion. + Reported by Vivek P. Singhal. + + * eval.c (eval_lex): Admit both lower and upper case letters for + bases greater than 10. Only lower case letters were accepted. + + * eval.c (eval_lex): Recognize 0bDIGITS and 0rRADIX:DIGITS syntax. + Reported by Krste Asanovic. + + * eval.c: Rename NOT to LNOT. Add XOR, NOT, LSHIFT and RSHIFT. + * eval.c (logical_not_term): New name for not_term. + * eval.c (xor_term): New, between or_term and and_term. + * eval.c (not_term): New, between and_term and logical_not_term. + * eval.c (shift_term): New, between cmp_term and add_term. + Reported by Krste Asanovic: ~, ^, <<, >>. + Reported by Ben A. Mesander: ** vs ^. + + * m4.c: Delete xmalloc.c, xrealloc.c, xstrdup.c. + * m4.h: Delete xrealloc.c. + * lib/xmalloc.c: New, from elsewhere. + * lib/xstrdup.c: New, from elsewhere. + * lib/Makefile.in: Distribute and compile them. + + * m4.c: Change progname to program_name. + * builtin.c, eval.c, m4.c, m4.h: Rename error to m4error. + * lib/error.c: New, from elsewhere. + * lib/Makefile.in: Distribute and compile error.c. + * configure.in: Check AC_VPRINTF and for strerror. + * m4.c: Delete cmd_error. Use error instead. + * m4.c: Change label capitalisation to "ERROR", "Warning", etc. + + * m4.h: Delete #define const, let Autoconf takes care of this. + + * m4.c: Remove all code conditionalized by IMPLEMENT_M4OPTS. + Merge parse_args into main. Declare argv to be `char *const *', + then remove superfluous casts. + + * m4.c: Rename --no-gnu-extensions to --traditional. + Reported by Ben A. Mesander. + + * m4.c (usage): Add a status parameter. Supply one in various + calls. Add --help processing. Remove -V for --version. + + * lib/Makefile.in: Put $(CFLAGS) last in .c.o rule. + + * lib/Makefile.in: Have an AR=ar declaration. + Reported by Eric Backus. + Reported by Bjorn R. Bjornsson. + Reported by Tom Tromey. + Reported by Kristine Lund. + Reported by Marion Hakanson. + +Sat Oct 30 12:51:47 1993 Francois Pinard (pinard@icule) + + * Makefile.in (m4.info): Use -I$(srcdir) on $(MAKEINFO). + Reported by Noah Friedman. + +Mon Oct 25 14:58:48 1993 Francois Pinard (pinard@icule) + + * Makefile.in: Remove MDEFINES and cleanup. + +Wed Jun 9 14:59:46 1993 Francois Pinard (pinard@icule) + + * Makefile.in (dist): Replace "echo `pwd`" by a mere "pwd". + Create a gzip file. + +Sat Feb 6 14:59:22 1993 Francois Pinard (pinard@icule) + + * Makefile.in, lib/Makefile.in, check/Makefile.in: In dist goals, + ensure 777 mode for directories, so older tar's will restore file + modes properly. + +Sun Jan 17 15:38:05 1993 Francois Pinard (pinard@icule) + + * Makefile.in, lib/Makefile.in: Put $(CFLAGS) after $(CPPFLAGS), + so the installer can override automatically configured choices. + Reported by Karl Berry. + +Fri Jan 15 16:07:00 1993 Francois Pinard (pinard@icule) + + * lib/vfprintf.c: Stolen from Oleo distribution and adapted. The + previous version was not working properly on m68k-hp-bsd4.3. + Reported by Roland McGrath. + + * lib/_doprnt.c: Stolen from Oleo distribution. + * configure.in: Check for _doprnt.c if vfprintf.c selected. + * lib/Makefile.in: Distribute _doprnt.c. + Do not distribute regex.[ch].old anymore. + +Fri Jan 1 19:42:23 1993 Francois Pinard (pinard at icule) + + * Makefile.in, lib/Makefile.in: Reinstate $(CPPFLAGS), use it. + Richard wants it there. + +Sun Dec 27 07:01:54 1992 Francois Pinard (pinard at icule) + + * Makefile.in: Add DEFS to MDEFINES. + * lib/Makefile.in (.c.o): Remove $(CPPFLAGS). + (libm4.a): Remove the library before creating it. + (distclean): Remove tags and TAGS too. + +Wed Dec 23 12:46:55 1992 Francois Pinard (pinard at icule) + + * Makefile.in (dvi, m4.dvi): New goals. + + * builtin.c, eval.c, format.c, input.c, m4.[ch], m4.texinfo, + macro.c, output.c, path.c, symtab.c: Change Copyright from + 1989-1992 to the explicit enumeration 1989, 1990, 1991, 1992. + + * examples/divert.m4: Deleted, this bug has been corrected. + + * Makefile.in (texclean, mostlyclean): New goals. + + * Makefile.in (clean): Remove clutter from ansi2knr. + Reported by Pierre Gaumond. + Reported by Greg A. Woods. + +Sun Dec 20 10:40:20 1992 Francois Pinard (pinard at icule) + + * Makefile.in: Remove $(CPPFLAGS) from the .c.o rule. The user + might well use CFLAGS is s/he needs it. + + * Makefile.in: Allow installation of info files from a separate + build directory. + Reported by Jason Merrill. + Reported by David MacKenzie. + Reported by Skip Montanaro. + Reported by Erez Zadok. + Reported by Assar Westerlund. + +Sat Dec 19 08:21:34 1992 Francois Pinard (pinard at icule) + + * Release 1.0.3 + This is still a beta release for the future GNU m4 version 1.1. + + * lib/alloca.c: New, from elsewhere. + * lib/Makefile.in: Distribute it. Define and use $(ALLOCA). + + * m4.h: Do not define index/rindex if already defined. If + FALSE/TRUE are already defined, do not redefine them, but merely + define boolean typedef to int. + + * Makefile.in: Use $(DEFS) while compiling ansi2knr. + * ansi2knr.c: Rewrite #ifdef HAVE_STRING_H || STDC_HEADERS, + because some C compilers do not like connectives with #ifdef. + * m4.h: Define `volatile' only if __GNUC__, instead of once for + __GNUC__ and once for __STDC__. + * lib/regex.h: Leave const alone, AC_CONST will take care of it. + + * checks/Makefile.in: Use .all_stamp instead of $(CHECKS) for + Makefile dependencies. Without it, make keeps destroying and + remaking $(CHECKS) in a loop (why?). Distribute .all_stamp. + + * m4.h, m4.c, builtin.c, output.c: Change all divertion/DIVERTION + to diversion/DIVERSION, this was a spelling error. + + * m4.c: Declare version[], remove #include "version.h". + * version.h: Deleted. + * Makefile.in: Remove references to version.h. + + * output.c (shipout_text): Centralize all `#line NUM ["FILE"]' + production, by using a simpler and more robust algorithm. This + solves the problem of synclines sometimes written in the middle of + an output line. Delete sync_line() and output_lines variable. + * m4.h: Remove sync_line prototype and output_lines declaration. + * input.c (next_char), output.c (shipout_text): Remove references + to output_lines. + * input.c (push_file, pop_file): Merely put the value -1 in + output_current_line instead of calling sync_line, for delaying a + single `#line NUM FILE' before next output line. Do not test + for sync_output, because this is unnecessary clutter. + * output.c (make_divertion, insert_divertion): Idem. + * input.c: Rename must_advance_line to start_of_input_line, for + consistency. + + * debug.c (trace_header): Select a new debug line format, which + better complies with GNU standards for formatting error messages. + With option `-dfl', M-x next-error might be used on the output. + * m4.c (vmesg): Adjust format of error output to GNU standards. + * m4.texinfo: Adjust examples for `make check' to work. + + * m4.h, builtin.c, debug.c, input.c, macro.c, path.c: Use upper + case for enum debug_info constants, which were all lower case. + + * builtin.c (m4_regexp, m4_patsubst): Use re_search instead of + re_search_2. + * lib/regex.[ch]: Use new version from textutils 1.3.6, with some + collected patches. I tried a few times using newer regex.[ch], it + mysteriously stopped aborting with this one. Insecure feeling... + * lib/Makefile.in: Distribute regex.[ch].old, just in case! + +Fri Dec 18 11:08:03 1992 Francois Pinard (pinard at icule) + + * m4.c: Change `--no-warnings' to `--silent'. + Reported by David MacKenzie. + + * m4.c: Put all M4OPTS code upon IMPLEMENT_M4OPTS control, and + leave it off for now. See comment in m4.c for justification. + Reported by David MacKenzie. + + * configure.in: Replace AC_USG by AC_HAVE_HEADERS(string.h). + * m4.h, ansi2knr.c, lib/regex.h: Replace USG by HAVE_STRING_H. + + * Makefile.in: Add a new `info' goal. Use macro MAKEINFO. + + * Makefile.in: Ensure recursive cleaning is done before local + cleaning for all clean goals. + + * builtin.c (ntoa): Ensure the value is always interpreted as a + signed quantity, whatever the radix is. + +Wed Nov 18 07:57:19 1992 Jim Meyering (meyering@idefix) + + * builtin.c, format.c, input.c: Split long lines. + * m4.c: Use typedef macro_definition instead of struct + macro_definition. + * symtab.c: Use typedef symbol instead of struct symbol. + +Tue Nov 17 01:58:40 1992 Francois Pinard (pinard at icule) + + * *.[ch]: Remove all trailing whitespace, in code and comments. + + * configure.in: Find some awk. + * Makefile.in: Add $(AWK) to MDEFINES. + * checks/Makefile.in: Transmit $(AWK) to get_them. + * checks/get_them: Use $AWK instead of gawk. Add a close in the + awk script when switching files, because without this, mawk runs + out of file descriptors. + +Mon Nov 16 20:42:56 1992 Francois Pinard (pinard at icule) + + * Makefile.in (realclean): Delete m4.info*. + Reported by Jim Meyering. + + * Makefile.in: Adjust and link with checks/Makefile. + * checks/Makefile.in: New. + * configure.in: Output checks/Makefile. + + * checks/get_them: Have the dnl header of each test more + recognizable by next-error, also use a better message. + +Mon Nov 16 07:48:52 1992 Jim Meyering (meyering@idefix) + + * m4.h [__GNUC__]: Use __volatile__ instead of `volatile.' + And use that only if __GNUC__ since we're using it's GCC-specific + semantics that tell the compiler the associated function doesn't + return. + + * builtin.c (substitute): Don't use character as an array index. + (dumpdef_cmp): Make formal arguments `const void *' to avoid + warnings with gcc -W -Wall on systems with qsort prototype. + (m4_errprint): Cast obstack_finish to `char *' to avoid warnings + from gcc -W -Wall. + + * eval.c (most functions): Add parentheses to assignments used + as truth values go avoid warnings from gcc -Wall. + + * input.c, m4.c, output.c, path.c, symtab.c: Declare static + any functions that don't need external scope. + + * builtin.c, debug.c, format.c, m4.c, m4.h, macro.c, symtab.c + (many functions and arrays): Declare `const'. + +Sun Nov 15 09:42:09 1992 Francois Pinard (pinard at icule) + + * *.[ch]: Rename nil to NULL, using the declaration from <stdio.h>, + removing the declaration from m4.h. Also rename false to FALSE + and true to TRUE. + + * lib/Makefile.in (Makefile): New goal. + + * Makefile.in, lib/Makefile.in: Add a .c.o rule, so CFLAGS is not + so heavily loaded. It gets more easily overridable, calling make. + Reported by Jim Meyering. + + * Makefile.in (dist): Get .fname from the current directory name, + instead of from version.h. I need updating many files manually, + when the version changes, version.h is just one of them. + +Sat Nov 14 11:01:20 1992 Francois Pinard (pinard at icule) + + * m4.h: Remove the tag `boolean' on the enum introducing typedef + `boolean'. This tag conflicts with <sys/types.h> on SVR4. + Reported by Tom McConnell. + +Fri Nov 13 00:12:50 1992 Francois Pinard (pinard at icule) + + * m4.texinfo: Correct the examples for 33.divert, 38.divnum, + 39.cleardiv, which were describing missing or spurious newlines. + Modify examples 52.eval, 53.esyscmd and 54.sysval so the results + do not depend on machine word size, `/bin/false' implementation, + or `wc' output format. `make check' is more dependable, now. + + * checks/check_them: Summarize the failed tests by listing their + name, at end. If none, issue `All checks successful'. Output + `Checking' instead of `Input file:'. + + * checks/get_them, checks/check_them: Reindented. + + * Makefile.in (dist): chmod a+r before making the tar file. + +Thu Nov 12 14:42:57 1992 Francois Pinard (pinard at icule) + + * builtin.c (m4_dnl): Diagnose any parameter to `dnl'. + + * input.c (next_token): Reinitialize token_buttom just after using + it as a watermark with obstack_free. Or else, a future token, big + enough for triggering reallocation of the obstack chunk, could + void the initialized value of token_buttom, later causing panic in + obstack_free. Rename token_buttom to token_bottom everywhere. + + * m4.h: Before declaring errno, first include <errno.h> and + ensure that it does not define errno. + Reported by Richard Stallman. + +Wed Nov 11 17:40:35 1992 Francois Pinard (pinard at icule) + + * builtin.c: Define and use DECLARE macro for builtins. + + * builtin.c (m4_ifelse): Avoid any diagnostic when exactly one + argument, this is a common idiom for introducing long comments. + + * builtin.c (m4_ifelse): If 3n + 2 arguments, diagnose missing + arguments. The last argument was silently ignored. + + * m4.c (cmd_error): Add a missing semicolon before va_end(). + +Tue Nov 10 08:57:05 1992 Francois Pinard (pinard at icule) + + * Makefile.in: Now handle protoized sources. Define and use U. + Compile and use ansi2knr with old compilers. Update DISTFILES. + Add `aclocal.m4' to `configure' dependencies. + * ansi2knr.c: New, from Ghostscript distribution. + * configure.in: Define U through FP_PROTOTYPES for old compilers. + Add AC_ISC_POSIX, AC_CONST, AC_SIZE_T. + * aclocal.m4: New, provide FP_PROTOTYPES. + * m4.h: Conditionnaly protoized through Args, save for varags. + * builtin.c: Protoized. Then: + Include <sys/types.h> if size_t is not defined, before "regex.h". + (m4_ifelse): Fetch built-in name properly for diagnostic. + (m4_dumpdef): Remove wrong (char *) cast calling dump_symbol. + (m4_regexp): Add const to `msg' declaration. + (m4_patsubst): Add const to `msg' declaration. + * debug.c: Protoized, save for varargs. + * eval.c: Protoized. + * format.c: Protoized. + * input.c: Protoized. + * m4.c: Protoized, save for varargs. Then: + (xfree): Accept void * instead of char *. + (xmalloc): Return void * instead of char *. + (xrealloc): Accept and return void * instead of char *. + * macro.c: Protoized. + * output.c: Protoized. + * path.c: Protoized. Then cast some (char *) over xmalloc's. + * symtab.c: Protoized. + +Fri Nov 6 02:05:21 1992 Francois Pinard (pinard at icule) + + * m4.texinfo: Remove directory from diagnostics in 30.include, + 51.eval, 56.errprint and 57.m4exit tests. + + * m4.h: Remove declarations for int or void system functions, they + cause more conflicting trouble than they make good. + + * configure.in: Avoid configuration header file. Add some tests. + * m4.h: Remove #include "config.h". + * Makefile.in, lib/Makefile.in: Implement Autoconf interface. + Then, rewritten for better compliance with GNU standards. + +Thu Nov 5 12:37:13 1992 Francois Pinard (pinard at icule) + + * format.c (format): Avoid syntax error if not HAVE_EFGCVT, + because of a misplaced #endif. + + * Many *.[hc] files: Correct intra-line spacing here and there, + according to GNU indent 1.6 advice. + + * configure.in: New, using Autoconf 1.2. + * m4.h: Reverse NO_MEMORY_H to NEED_MEMORY_H. + * Delete old configure.in, configure, etc/configure.in, + etc/configure, lib/configure.in, lib/configure and config/*. + Reported by Jason Merrill. + + * symtab.c (hash): Change (char) NULL to '\0'. + Reported by Jason Merrill. + + * Delete .vers, etc/newdist.sh, etc/newvers.sh and + etc/nextvers.sh. Release numbers will be edited `by hand'. + * version.h: De-automatize, force value in. + + * m4.c: Changes in order to use a newer getopt.h. + Reported by David MacKenzie. + + * checks/: New name for examples/. + * checks/get_them: New location for etc/get_examples. + * checks/check_them: New location for etc/check_examples. + * Makefile.in, checks/get_them, checks/check_them: Adjust. + * lib/vfprintf.c: New location for etc/vfprintf.c. + * Delete empty etc/. + * examples/: New name for test/. + +Tue Mar 10 00:29:46 1992 Francois Pinard (pinard at icule) + + * Makefile.in (check): Add m4 as dependency. + + * m4.c: Accept --no-warnings instead of --no_warnings, and + --no-gnu-extensions instead of --no_gnu_extensions. Make the + usage message more informative. + Reported by David MacKenzie. + +Mon Mar 9 14:53:40 1992 Francois Pinard (pinard at icule) + + * etc/check_examples: New name for check_examples.sh. + * etc/get_examples: New name for get_examples.sh. + * Makefile.in, etc/Makefile.in: Use new names. + + * Makefile.in: Transmit $(CC) while making in lib. + + * Many *.[hc] files: GNU indent'ed, with further fine tuning of + code disposition by hand. + +Sun Mar 8 11:01:55 1992 Francois Pinard (pinard at icule) + + * m4.h: Delete definitions for abort() and exit(). + Reported by Richard Stallman. + + * config/hmake-unicos, config/s-unicos.h: New files. + Reported by Hal Peterson. + + * eval.c (exp_term): Have N^0 return 1. + Reported by Michael Fetterman. + + * eval.c, input.c, m4.h: Remove last comma in enums. + Reported by Mike Lijewski. + + * Transfer of maintenance duties from Rene' to Franc,ois. + +Thu Oct 24 15:18:46 1991 Rene' Seindal (seindal at diku.dk) + + * Release 1.0. Many thanks to those, who provided me with bug + reports and feedback. + + * Uses GNU configure, taken from the gdb distribution. + + * Uses GNU getopt(), with long option names. + + * The -Q/+quiet option is added, which suppresses warnings about + missing or superflous arguments to built-in macros. + + * Added default options via the M4OPTS environment variable. + + * The built-in format can now be configured to use sprintf as + the formatting engine, for systems without [efg]cvt(3). + + * GNU library code is moved to the ./lib subdirectory; other + utility files are now in ./etc. + + * Several minor bugs have been fixed. + +Fri Jul 26 15:28:42 1991 Rene' Seindal (seindal at diku.dk) + + * Fixed various bugs. Release 0.99, manual 0.09. Many thanks to + Francois Pinard and Roland H. Pesch for providing me with reports. + + * The builtins incr and decr are now implemented without use of + eval. + + * The builtin indir is added, to allow for indirect macro calls + (allows use of "illegal" macro names). + + * The debugging and tracing facilities has been enhanced + considerably. See the manual for details. + + * The -tMACRO option is added, marks MACRO for tracing as soon + as it is defined. + + * Builtins are traced after renaming iff they were before. + + * Named files can now be undiverted. + + * The -Nnum option can be used to increase the number of + divertions available. + + * Calling changecom without arguments now disables all comment + handling. + + * The function m4_patsubst() is now consistently declared + static. + + * A bug in dnl is fixed. + + * A bug in the multi-character quoting code is fixed. + + * Several typos in the manual has been corrected. More probably + persist. + + * The m4.info file is now installed along with the program. + +Thu Nov 15 21:51:06 1990 Rene' Seindal (seindal at diku.dk) + + * Updated and enhanced version. Release 0.75, manual 0.07. + + * Implemented search path for include files (-I option and + M4PATH envronment variable). + + * Implemented builtin "format" for printf-like formatting. + + * Implemented builtin "regexp" for searching for regular + expressions. + + * Implemented builtin "patsubst" for substitution with regular + expressions. + + * Implemented builtin "esyscmd", which expands to a shell + commands output. + + * Implemented "__file__" and "__line__" for use in error + messages. + + * Implemented character ranges in "translit". + + * Implemented control over debugging output. + + * Implemented multi-character quotes. + + * Implemented multi-character comment delimiters. + + * Changed predefined macro "gnu" to "__gnu__". + + * Changed predefined macro "unix" to "__unix__", when the -G + option is not used. With -G, "unix" is still defined. + + * Changed "shift", "$@" and "$*" to not insert spaces afters + commas. + + * Added program name to error messages. + + * Fixed two missing null bytes bugs. + +Mon Jan 22 21:08:52 1990 Rene' Seindal (seindal at diku.dk) + + * Initial beta release. Release 0.50, manual 0.05. diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..0338fbce --- /dev/null +++ b/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source directory by typing `make clean'. To also remove the files + that `configure' created (so you can compile the package for a + different kind of computer), type `make distclean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Using a Different Build Directory +================================= + + You can compile the package in a different directory from the one +containing the source code. Doing so allows you to compile it on more +than one kind of computer at the same time. To do this, you must use a +version of `make' that supports the `VPATH' variable, such as GNU +`make'. `cd' to the directory where you want the object files and +executables to go and run the `configure' script. `configure' +automatically checks for the source code in the directory that +`configure' is in and in `..'. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Save the results of the tests in FILE instead of `config.cache'. + Set FILE to `/dev/null' to disable caching, for debugging + `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + @@ -0,0 +1,41 @@ +This GNU package is `localizable'. + +It can be made to speak your native language (or mother tongue). +If you are lucky, someone already did it for you. Check in the +distribution for `??.tt' files. `??' is usually one of: + + de for German + fr for French + nl for Dutch + sv for Swedish + +If your language is already supported, usage is quite simple. +Let's suppose, here, that you speak German. At the shell prompt, +merely execute `setenv LANG de' (in csh) or `export LANG; LANG=de' +(in sh). You may want to put this in your .login or .profile file. + +If your language is not supported, you have to work a bit for it. +Let's suppose again that you speak German. Eventually, when the GNU +locale package will have been published, you will follow these steps: + +1) Check with the maintainer if the work has been, or is being done. +2) Ensure that GNU locale has been installed on your site. +3) In the distribution, initialize `de.tt' by copying `fr.tt'. +4) Carefully edit `de.tt', replacing French parts by German parts. +5) Edit `Makefile.in', adding `de.msg' to the `CATALOGS =' line. +6) You do not need to reconfigure again. Execute `make install'. +7) Use `setenv LANG de', and just use the programs as usual. +8) Send `de.tt' to the maintainer, to be later distributed in GNU. + +But for the time being, GNU local package is still in alpha pretest, +so you are not completely free of me yet! Follow these steps: + +1) Check with the maintainer if the work has been, or is being done. +2) In the distribution, initialize `de.tt' by copying `fr.tt'. +3) Carefully edit `de.tt', replacing French parts by German parts. +4) Send `de.tt' to the maintainer, then wait for `de.msg' in return. +5) Install `de.msg' as `/usr/local/share/locale/de/PACKAGE.msg'. +6) Use `setenv LANG de', and just use the programs as usual. + +In step 5), of course, replace PACKAGE by the GNU package name, which +is usually the first word in the name of the distributed tar file. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..81175178 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS=intl po doc lib src checks examples + +EXTRA_DIST = LOCALE diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..3de59a49 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,138 @@ +# Main Makefile for GNU m4. +# Copyright (C) 1992, 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +PRODUCT = @PRODUCT@ +VERSION = @VERSION@ + +SHELL = /bin/sh +srcdir = @srcdir@ +VPATH = @srcdir@ +@SET_MAKE@ + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +CC = @CC@ +CFLAGS = @CFLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin +infodir = $(prefix)/info + +MDEFINES = CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' LIBS='$(LIBS)' \ +prefix='$(prefix)' exec_prefix='$(exec_prefix)' \ +bindir='$(bindir)' infodir='$(infodir)' + +SUBDIRS = doc lib src checks examples + +DISTFILES = README NEWS TODO THANKS COPYING INSTALL ChangeLog c-boxes.el \ +configure.in acconfig.h aclocal.m4 mkinstalldirs install-sh Makefile.in \ +stamp-h.in config.h.in configure BACKLOG + +.SUFFIXES: + +all install uninstall: config.h + for subdir in $(SUBDIRS); do \ + echo making $@ in $$subdir; \ + (cd $$subdir && $(MAKE) $(MDEFINES) $@) || exit 1; \ + done + +info dvi: + cd doc && $(MAKE) $@ + +check: all + cd checks && $(MAKE) $@ + +tags: + cd lib && $(MAKE) $@ + cd src && $(MAKE) $@ + +mostlyclean: mostlyclean-recursive mostlyclean-local + +clean: clean-recursive clean-local + +distclean: distclean-recursive distclean-local + rm config.status + +realclean: realclean-recursive realclean-local + rm config.status + +mostlyclean-recursive clean-recursive distclean-recursive realclean-recursive: + for subdir in $(SUBDIRS); do \ + target=`echo $@ | sed 's/-recursive//'`; \ + echo making $$target in $$subdir; \ + (cd $$subdir && $(MAKE) $$target) || exit 1; \ + done + +mostlyclean-local: + +clean-local: mostlyclean-local + +distclean-local: clean-local + rm -f Makefile config.cache config.h config.log stamp-h + +realclean-local: distclean-local + +dist: $(DISTFILES) + rm -rf $(PRODUCT)-$(VERSION) + mkdir $(PRODUCT)-$(VERSION) + chmod 777 $(PRODUCT)-$(VERSION) + @echo "Copying distribution files" + @for file in $(DISTFILES); do \ + ln $(srcdir)/$$file $(PRODUCT)-$(VERSION) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(PRODUCT)-$(VERSION); \ + done + for subdir in $(SUBDIRS); do \ + echo making $@ in $$subdir; \ + mkdir $(PRODUCT)-$(VERSION)/$$subdir; \ + chmod 777 $(PRODUCT)-$(VERSION)/$$subdir; \ + (cd $$subdir && $(MAKE) $@) || exit 1; \ + done + chmod -R a+r $(PRODUCT)-$(VERSION) + tar chozf $(PRODUCT)-$(VERSION).tar.gz $(PRODUCT)-$(VERSION) + rm -rf $(PRODUCT)-$(VERSION) + +# For an explanation of the following Makefile rules, see node +# `Automatic Remaking' in GNU Autoconf documentation. +Makefile: Makefile.in config.status + CONFIG_FILES=$@ CONFIG_HEADERS= ./config.status +config.status: configure + ./config.status --recheck +configure: configure.in aclocal.m4 + cd $(srcdir) && autoconf + +config.h: stamp-h +stamp-h: config.h.in config.status + CONFIG_FILES= CONFIG_HEADERS=config.h ./config.status +config.h.in: stamp-h.in +stamp-h.in: configure.in aclocal.m4 acconfig.h + cd $(srcdir) && autoheader + date > $(srcdir)/stamp-h.in + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: @@ -0,0 +1,200 @@ +GNU m4 NEWS - User visible changes. +Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. + +Version 1.4 - October 1994, by Franc,ois Pinard + +(No user visible changes) + +Version 1.3 - September 1994, by Franc,ois Pinard + +* Diversions are created as needed. Option `-N' is still accepted, but +otherwise ignored. Users should use only negative diversion numbers, +instead of high positive numbers, for diverting to nowhere. + +* Diversions should also work faster. No temporary files will be needed +at all if all diversions taken altogether do not use more than 512K. + +* Frozen state files may be produced with the `--freeze-state' (-F) +option and later brought back through the `--reload-state' (-R) option. + +Version 1.2 - July 1994, by Franc,ois Pinard + +* In patsubst(STRING, REGEXP, REPLACEMENT), \& in REPLACEMENT has been +changed to represent this part of STRING matched by the whole REGEXP, +instead of the whole STRING as before. \0 does the same, but emits a +diagnostic saying it will disappear in some subsequent release. + +* eval(EXPR) emits a diagnostic if EXPR has suffixed crumb. The same for +other numeric conversions in incr(), decr(), divert(), etc. + +* `--fatal-warnings' (-E) stops execution at first warning. + +* `--nesting-limit=LEVEL' (-L LEVEL) sets a limit to macro nesting. +It is initially fixed at 250. + +* `--word-regexp=REGEXP' (-W REGEXP) modifies macro name syntax, like +does the new `changeword(REGEXP)' macro. This feature is experimental, +tell me your opinions about it. You do need --enable-changeword at +configure time to get these things. Do *not* depend on them yet. + +* Trace output format is scannable by GNU Emacs' next-error function. + +* Stack overflow is detected and diagnosed on some capable systems. + +* Various bugs have been corrected, m4 should be more portable. See the +ChangeLog for details. + +Version 1.1 - November 1993, by Franc,ois Pinard + +Changes which might affect existing GNU m4 scripts: + +* Option `-V' has been removed, use `--version' instead. `--version' +writes on standard output instead of standard error, and inhibits any +script execution. + +* `--no-gnu-extensions' has been renamed `--traditional'. + +* In `eval', `^' used to indicate exponentiation, use `**' instead. + +* The automatic undiversion which takes place at end of all input is +forced into the main output stream. + +Changes which are unlikely to affect existing scripts: + +* `--help' prints an usage summary on standard output. Script execution +is then inhibited. + +* `--prefix-builtins' (-P) prefixes all builtin macros by `m4_'. + +* Most builtin macros for which arguments are mandatory, called without +any arguments, are no more recognized as builtin macros: they are +consequently copied verbatim to the output stream. + +* `define' and `pushdef' are usable with only one argument, they give +this argument an empty definition. + +* `eval' new operators for binary representation handling: `^' for +exclusive-or, `~' for the bitwise negation, `<<' and `>>' for shifts. + +* `eval' recognizes the notation 0bDIGITS for binary numbers and the +notation 0rRADIX:DIGITS for numbers in any radix from 1 to 36. + +Version 1.0.3 - December 1992, by Franc,ois Pinard + +Changes for the user: + +* `dnl' outputs a diagnostic if immediately followed by `('. Usually, +`dnl' is followed by newline or whitespace. + +* `ifelse' accepts without complaining the common idiom of having only +one argument. This is useful for introducing long comments. + +* `eval' always expresses values as signed, whatever the radix. + +* M4OPTS environment variable is no longer obeyed. + +* `--no-warnings' option is renamed `--silent'. + +* Debug lines use a new format more compatible with GNU standards. + +* Various bugs have been corrected. See the ChangeLog for details. + +Changes for the installer: + +* GNU m4 now uses an Autoconf-generated configure script, and should be +more easily portable in many ways. (Cray is not supported yet). + +* `make check' has been made more portable, expect no errors. + +Changes for the programmer: + +* Sources have been fully reindented to comply with GNU standards, and +cleaned up in many ways. + +* Sources have been protoized. Non-ANSI compilers are automatically +detected, then sources are unprotoized on the fly before compilation. + +* GNU m4 uses newer versions of obstack, regex, getopt, etc. + +Version 1.0 - October 1991, by Rene' Seindal + +* Uses GNU configure, taken from the gdb distribution. + +* Uses GNU getopt(), with long option names. + +* The -Q/+quiet option is added, which suppresses warnings about missing +or superflous arguments to built-in macros. + +* Added default options via the M4OPTS environment variable. + +* Several minor bugs have been fixed. + +Version 0.99 - July 1991, by Rene' Seindal + +* The builtins `incr' and `decr' are now implemented without use of +`eval'. + +* The builtin `indir' is added, to allow for indirect macro calls +(allows use of "illegal" macro names). + +* The debugging and tracing facilities has been enhanced considerably. +See the manual for details. + +* The -tMACRO option is added, marks MACRO for tracing as soon as it +is defined. + +* Builtins are traced after renaming iff they were before. + +* Named files can now be undiverted. + +* The -Nnum option can be used to increase the number of divertions +available. + +* Calling changecom without arguments now disables all comment handling. + +* A bug in `dnl' is fixed. + +* A bug in the multi-character quoting code is fixed. + +* Several typos in the manual has been corrected. More probably persist. + +Version 0.75 - November 1990, by Rene' Seindal + +* Implemented search path for include files (-I option and M4PATH +environment variable). + +* Implemented builtin `format' for printf-like formatting. + +* Implemented builtin `regexp' for searching for regular expressions. + +* Implemented builtin `patsubst' for substitution with regular +expressions. + +* Implemented builtin `esyscmd', which expands to a shell commands output. + +* Implemented `__file__' and `__line__' for use in error messages. + +* Implemented character ranges in `translit'. + +* Implemented control over debugging output. + +* Implemented multi-character quotes. + +* Implemented multi-character comment delimiters. + +* Changed predefined macro `gnu' to `__gnu__'. + +* Changed predefined macro `unix' to `__unix__', when the -G option is +not used. With -G, `unix' is still defined. + +* Added program name to error messages. + +* Fixed two missing null bytes bugs. + +Version 0.50 - January 1990, by Rene' Seindal + +* Initial beta release. + +Local Variables: +fill-column: 75 +End: @@ -0,0 +1,31 @@ +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 built-in 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' has been originally written by Rene' Seindal, from Denmark. +This release is to be considered as stable. + +If GNU `m4' is meant to serve GNU `autoconf', beware that `m4' +should be fully installed *prior to* configuring `autoconf' itself. + +In the subdirectory `examples' you will find various m4 files, ranging +from trivial test files to rather advanced macros. If you intend to +use m4 seriously, you might find useful material down there. + +See file `BACKLOG' for a summary of pending mail and articles. +See file `COPYING' for copying conditions. +See file `INSTALL' for compilation and installation instructions. +See file `NEWS' for a list of major changes in the current release. +See file `THANKS' for a list of contributors. + +By using `./configure --enable-changeword', you get an experimental +feature which allows for changing the syntax of what is a "word" in +`m4'. This might go away, so don't count on it yet. + +Send bug reports to `bug-gnu-utils@prep.ai.mit.edu'. A bug report is +an adequate description of the problem: your input, what you expected, +what you got, and why this is wrong. Diffs are welcome, but they only +describe a solution, from which the problem might be uneasy to infer. diff --git a/README-alpha b/README-alpha new file mode 100644 index 00000000..4ed792df --- /dev/null +++ b/README-alpha @@ -0,0 +1,12 @@ +This is a alpha version of GNU m4. + +Please see the file TODO for a list of open problems and known bugs. + +Send bug reports, comments or ideas to `bug-m4@gnu.org'. A bug report +is an adequate description of the problem: your input, what you +expected, what you got, and why this is wrong. Diffs are welcome, but +they only describe a solution, from which the problem might be uneasy to +infer. Don't forget all relevant information about your operating +system, compiler, libraries, ... + +GNU m4 has a web-site at http://www.seindal.dk/rene/gnu/ @@ -0,0 +1,71 @@ +GNU m4 THANKS file + +GNU m4 has originally been written by Rene' Seindal. Many people +further contributed to GNU m4 by reporting problems, suggesting +various improvements or submitting actual code. Here is a list of +these people. Help me keep it complete and exempt of errors. + +Akiko Matsushita matusita@sra.co.jp +Alan Magnuson awm@osc.edu +Alexander Lehmann alex@hal.rhein-main.de +Amos Shapira amoss@cs.huji.ac.il +Andreas Gustafsson gson@niksula.hut.fi +Andreas Schwab schwab@ls5.informatik.uni-dortmund.de +Assar Westerlund assar@nada.kth.se +Ben A. Mesander ben@piglet.cr.usgs.gov +Bengt Mertensson bengt@mathematik.uni-bremen.de +Bernhard Daeubler daeb@physik.uni-ulm.de +Bjorn R. Bjornsson brb@falcon.is +Brendan Kehoe brendan@cygnus.com +David J. MacKenzie djm@uunet.uu.net +Erez Zadok ezk@cs.columbia.edu +Eric Allman eric@cs.berkeley.edu +Eric Backus ericb@lsid.hp.com +Franc,ois Pinard pinard@iro.umontreal.ca +Geoff Russell grussell@guest.adelaide.edu.au +Greg A. Woods woods@web.apc.org +Hal Peterson hrp@pecan.cray.com +Hoang Uong hoang@ornews.intel.com +Ian Taylor ian@cygnus.com +Jason Merrill jason@jarthur.claremont.edu +Jim Avera jima@netcom.com +Jim Kingdom kingdon@cygnus.com +Jim Meyering meyering@acm.org +Joel Sherrill jsherril@uahcs2.cs.uah.edu +John David Anglin dave@hiauly1.hia.nrc.ca +Joseph E. Sacco jsacco@ssl.com +Karl Berry karl@cs.umb.edu +Karl Vogel vogelke@c-17igp.wpafb.af.mil +Kaveh R. Ghazi ghazi@noc.rutgers.edu +Kristine Lund lund@lpnaxp.in2p3.fr +Krste Asanovic krste@icsi.berkeley.edu +Marion Hakanson hakanson@cse.ogi.edu +Mark Seiden mis@seiden.com +Matthias Rabe rabe@mathematik.uni-bielefeld.de +Michael Fetterman mafetter@ichips.intel.com +Michael L. Welcome welcome@bigbird.llnl.gov +Mike Lijewski lijewski@theory.tc.cornell.edu +Nick S. Kanakakorn skanan@otl.scu.edu +Nicolas Pioch pioch@inf.enst.fr +Noah Friedman friedman@gnu.ai.mit.edu +Pete Chown pete.chown@dale.dircon.co.uk +Pierre Gaumond gaumondp@ere.umontreal.ca +Pierre Mathieu mathieu@geod.emr.ca +Robert Bernstein rocky@panix.com +Rene' Seindal seindal@diku.dk +Richard Stallman rms@gnu.ai.mit.edu +Roland H. Pesch roland@wrs.com +Roland McGrath roland@gnu.ai.mit.edu +Scott Bartram deneb!scottb +Simon Leinen simon@lia.di.epfl.ch +Skip Montanaro skip@automatrix.com +Stephen Perkins perkins@cps.msu.edu +Steve Williamson willy@uinpla.npl.uiuc.edu +Thorsten Ohl ohl@physics.harvard.edu +Tom McConnell tmcconne@sedona.intel.com +Tom Quinn trq@dionysos.thphys.ox.ac.uk +Tom Tromey tromey@cns.caltech.edu +Ulrich Drepper drepper@ira.uka.de +Vern Paxson vern@ee.lbl.gov +Vivek P. Singhal singhal@cs.utexas.edu +Walter Wong wcw+@cmu.edu @@ -0,0 +1,41 @@ +TODO file for GNU m4 + +Tell <pinard@iro.umontreal.ca> if you feel like volunteering for any +of these ideas, listed more or less in decreasing order of priority. + +* Features or problems + - Update documentation from accumulated mail about it + - Changeword without arguments should restore default behavior + - Study synclines at the very beginning of each diverted sequence + - Make eval work on bignums - the 32 bits limit is artificial + From Krste Asanovic <krste@icsi.berkeley.edu>, 1993-03-20 + +* Optimization and clean up + - Check for memory leaks and uninitialized reads + From Vern Paxson <vern@horse.ee.lbl.gov> on 1993-12-06 + - Simplify format/ecvt code, together with HAVE_EFGCVT + - Finalize the stdarg vs varargs thing + - Profile GNU m4 and speed it up + From David J. MacKenzie <djm@eng.umd.edu>, 1993-01-20 + + GNU m4 should be sped up by a factor of three for competing + with other versions (I think that the lexer is not agressive + enough and too often return single characters; obstacks might + be a little abused, too). + - Have NULs go really undisturbed through GNU m4 + See `dumpdef' and debugging section, which abuses %s + From Thorsten Ohl <ohl@chico.harvard.edu>, 1992-12-21 + + path.c (add_include_directory): Why the '\0' terminator? + + GNU m4 is lousy regarding NULs in streams (this would require + maintaining the string lengths, and avoiding strlen, strcpy, + etc.). + - Clean up the obstack.[ch] code + - Use rx.[ch] instead of regex.[ch] + From Hal Peterson <hrp@ironwood.cray.com>, 1994-04-22 + +Local Variables: +mode: outline +outline-regexp: " *[-+*.] \\|" +End: diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 00000000..807221aa --- /dev/null +++ b/acconfig.h @@ -0,0 +1,36 @@ +/* Special definitions for GNU m4, processed by autoheader. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. + Francois Pinard <pinard@iro.umontreal.ca>, 1993. +*/ + +/* Define to 1 if the changeword(REGEXP) functionnality is wanted. */ +#undef ENABLE_CHANGEWORD + +/* Define to 1 if you have ecvt(3), fcvt(3) and gcvt(3), define to 2 if + these are declared in <stdlib.h>. */ +#undef HAVE_EFGCVT + +/* Define to 1 if #include <signal.h> declares struct sigcontext */ +#undef HAVE_SIGCONTEXT + +/* Define to the name of the distribution. */ +#undef PRODUCT + +/* Define to 1 if ANSI function prototypes are usable. */ +#undef PROTOTYPES + +/* Define to int if rlim_t is not defined in sys/resource.h */ +#undef rlim_t + +/* Define to struct sigaltstack if stack_t is not defined in sys/signal.h */ +#undef stack_t + +/* Define to 1 if using stack overflow detection. */ +#undef USE_STACKOVF + +/* Define to the version of the distribution. */ +#undef VERSION + +/* Define to 1 for better use of the debugging malloc library. See + site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz. */ +#undef WITH_DMALLOC diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 00000000..a670f1cb --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,418 @@ +#serial 1 + +dnl FIXME: put these prerequisite-only *.m4 files in a separate +dnl directory -- otherwise, they'll conflict with existing files. + +dnl These are the prerequisite macros for GNU's error.c file. +AC_DEFUN(jm_PREREQ_ERROR, +[ + AC_CHECK_FUNCS(strerror strerror_r vprintf doprnt) + AC_HEADER_STDC +]) +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# Modified for GNU m4 by René Seindal (rene@seindal.dk) + +# serial 5 + +AC_DEFUN(AM_WITH_NLS, + [AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) + + USE_INCLUDED_LIBINTL=no + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + AC_DEFINE(ENABLE_NLS) + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc, + [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")], + gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)]) + + if test "$gt_cv_func_gettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, gettext, + [LIBS="$LIBS -lintl" + gt_cv_func_gettext_libintl=yes], + [gt_cv_func_gettext_libintl=no])]) + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + ]) + + if test "$CATOBJEXT" = "NONE"; then + AC_MSG_CHECKING([whether catgets can be used]) + AC_ARG_WITH(catgets, + [ --with-catgets use catgets functions if available], + nls_cv_use_catgets=$withval, nls_cv_use_catgets=no) + AC_MSG_RESULT($nls_cv_use_catgets) + + if test "$nls_cv_use_catgets" = "yes"; then + dnl No gettext in C library. Try catgets next. + AC_CHECK_LIB(i, main) + AC_CHECK_FUNC(catgets, + [AC_DEFINE(HAVE_CATGETS) + INTLOBJS="\$(CATOBJS)" + AC_PATH_PROG(GENCAT, gencat, no)dnl + if test "$GENCAT" != "no"; then + AC_PATH_PROG(GMSGFMT, gmsgfmt, no) + if test "$GMSGFMT" = "no"; then + AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no) + fi + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.cat + INSTOBJEXT=.cat + DATADIRNAME=lib + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi]) + fi + fi + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + INTLOBJS="\$(GETTOBJS)" + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_SUBST(MSGFMT) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(AM_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next]) + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + AC_CHECK_FUNCS(stpcpy) + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + AC_DEFINE(HAVE_STPCPY) + fi + + AM_LC_MESSAGES + AM_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl The reference to <locale.h> in the installed <libintl.h> file + dnl must be resolved because we cannot expect the users of this + dnl to define HAVE_LOCALE_H. + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include <locale.h>" + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header <locale.h>. Take care yourself. */" + fi + AC_SUBST(INCLUDE_LOCALE_H) + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + test -d intl || mkdir intl + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed + fi + dnl po2tbl.sed is always needed. + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed + + dnl In the intl/Makefile.in we have a special dependency which makes + dnl only sense for gettext. We comment this out for non-gettext + dnl packages. + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + AC_SUBST(GT_NO) + AC_SUBST(GT_YES) + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl *** For now the libtool support in intl/Makefile is not for real. + l= + AC_SUBST(l) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper <drepper@cygnus.com>, 1996. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in <locale.h>. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES) + fi + fi]) + +#serial 2 + +dnl Derived from code in GNU grep. + +AC_DEFUN(jm_WITH_REGEX, + [ + dnl Even packages that don't use regex.c can use this macro. + dnl Of course, for them it doesn't do anything. + + syscmd([test -f lib/regex.c]) + ifelse(sysval, 0, + [ + AC_ARG_WITH(included-regex, + [ --without-included-regex don't compile regex (use with caution)], + jm_with_regex=$withval, + jm_with_regex=yes) + if test "$jm_with_regex" = yes; then + LIBOBJS="$LIBOBJS regex.o" + fi + ], + ) + ] +) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..90812401 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,85 @@ +# Local additions to Autoconf macros. +# Copyright (C) 1992, 1994 Free Software Foundation, Inc. +# Francois Pinard <pinard@iro.umontreal.ca>, 1992. + +# @defmac AC_PROG_CC_STDC +# @maindex PROG_CC_STDC +# @ovindex CC +# If the C compiler in not in ANSI C mode by default, try to add an option +# to output variable @code{CC} to make it so. This macro tries various +# options that select ANSI C on some system or another. It considers the +# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and +# handles function prototypes correctly. +# +# If you use this macro, you should check after calling it whether the C +# compiler has been set to accept ANSI C; if not, the shell variable +# @code{ac_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source +# code in ANSI C, you can make an un-ANSIfied copy of it by using the +# program @code{ansi2knr}, which comes with Ghostscript. +# @end defmac + +define(fp_PROG_CC_STDC, +[AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C) +AC_CACHE_VAL(ac_cv_prog_cc_stdc, +[ac_cv_prog_cc_stdc=no +ac_save_CFLAGS="$CFLAGS" +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX -Aa -D_HPUX_SOURCE +# SVR4 -Xc +for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc +do + CFLAGS="$ac_save_CFLAGS $ac_arg" + AC_TRY_COMPILE( +[#if !defined(__STDC__) || __STDC__ != 1 +choke me +#endif +], [int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);};], +[ac_cv_prog_cc_stdc="$ac_arg"; break]) +done +CFLAGS="$ac_save_CFLAGS" +]) +AC_MSG_RESULT($ac_cv_prog_cc_stdc) +case "x$ac_cv_prog_cc_stdc" in + x|xno) ;; + *) CC="$CC $ac_cv_prog_cc_stdc" ;; +esac +]) + +# Check for function prototypes. + +AC_DEFUN(fp_C_PROTOTYPES, +[AC_REQUIRE([fp_PROG_CC_STDC]) +AC_MSG_CHECKING([for function prototypes]) +if test "$ac_cv_prog_cc_stdc" != no; then + AC_MSG_RESULT(yes) + AC_DEFINE(PROTOTYPES) + U= ANSI2KNR= +else + AC_MSG_RESULT(no) + U=_ ANSI2KNR=ansi2knr +fi +AC_SUBST(U)dnl +AC_SUBST(ANSI2KNR)dnl +]) + +# Check if --with-dmalloc was given. + +AC_DEFUN(fp_WITH_DMALLOC, +[AC_MSG_CHECKING(if malloc debugging is wanted) +AC_ARG_WITH(dmalloc, +[ --with-dmalloc use dmalloc, as in dmalloc.tar.gz from + @/ftp.antaire.com:antaire/src/dmalloc.], +[if test "$withval" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_DMALLOC) + LIBS="$LIBS -ldmalloc" + LDFLAGS="$LDFLAGS -g" +else + AC_MSG_RESULT(no) +fi], [AC_MSG_RESULT(no)])]) + diff --git a/acm4/Makefile.am b/acm4/Makefile.am new file mode 100644 index 00000000..1d2df7af --- /dev/null +++ b/acm4/Makefile.am @@ -0,0 +1,12 @@ +EXTRA_DIST = $(ACINCLUDES_M4) + +ACINCLUDES_M4 = error.m4 gettext.m4 regex.m4 + +ACINCLUDE_M4 = $(top_srcdir)/acinclude.m4 + +all: $(ACINCLUDE_M4) + +$(ACINCLUDE_M4): $(ACINCLUDES_M4) + cat $(ACINCLUDES_M4) > $@ + cd $(top_srcdir) && $(ACLOCAL) +# cd $(top_srcdir) && $(MAKE) diff --git a/acm4/Makefile.in b/acm4/Makefile.in new file mode 100644 index 00000000..77d1cdd7 --- /dev/null +++ b/acm4/Makefile.in @@ -0,0 +1,186 @@ +# Makefile.in generated automatically by automake 1.3b from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 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. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +PACKAGE = @PACKAGE@ +PERL = @PERL@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +STACKOVF = @STACKOVF@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +l = @l@ + +EXTRA_DIST = $(ACINCLUDES_M4) + +ACINCLUDES_M4 = error.m4 gettext.m4 regex.m4 + +ACINCLUDE_M4 = $(top_srcdir)/acinclude.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps acm4/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = acm4 + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +all: $(ACINCLUDE_M4) + +$(ACINCLUDE_M4): $(ACINCLUDES_M4) + cat $(ACINCLUDES_M4) > $@ + cd $(top_srcdir) && $(ACLOCAL) +# cd $(top_srcdir) && $(MAKE) + +# 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/acm4/error.m4 b/acm4/error.m4 new file mode 100644 index 00000000..eb0f776b --- /dev/null +++ b/acm4/error.m4 @@ -0,0 +1,11 @@ +#serial 1 + +dnl FIXME: put these prerequisite-only *.m4 files in a separate +dnl directory -- otherwise, they'll conflict with existing files. + +dnl These are the prerequisite macros for GNU's error.c file. +AC_DEFUN(jm_PREREQ_ERROR, +[ + AC_CHECK_FUNCS(strerror strerror_r vprintf doprnt) + AC_HEADER_STDC +]) diff --git a/acm4/gettext.m4 b/acm4/gettext.m4 new file mode 100644 index 00000000..969d0922 --- /dev/null +++ b/acm4/gettext.m4 @@ -0,0 +1,384 @@ +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# Modified for GNU m4 by René Seindal (rene@seindal.dk) + +# serial 5 + +AC_DEFUN(AM_WITH_NLS, + [AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) + + USE_INCLUDED_LIBINTL=no + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + AC_DEFINE(ENABLE_NLS) + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc, + [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")], + gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)]) + + if test "$gt_cv_func_gettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, gettext, + [LIBS="$LIBS -lintl" + gt_cv_func_gettext_libintl=yes], + [gt_cv_func_gettext_libintl=no])]) + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + ]) + + if test "$CATOBJEXT" = "NONE"; then + AC_MSG_CHECKING([whether catgets can be used]) + AC_ARG_WITH(catgets, + [ --with-catgets use catgets functions if available], + nls_cv_use_catgets=$withval, nls_cv_use_catgets=no) + AC_MSG_RESULT($nls_cv_use_catgets) + + if test "$nls_cv_use_catgets" = "yes"; then + dnl No gettext in C library. Try catgets next. + AC_CHECK_LIB(i, main) + AC_CHECK_FUNC(catgets, + [AC_DEFINE(HAVE_CATGETS) + INTLOBJS="\$(CATOBJS)" + AC_PATH_PROG(GENCAT, gencat, no)dnl + if test "$GENCAT" != "no"; then + AC_PATH_PROG(GMSGFMT, gmsgfmt, no) + if test "$GMSGFMT" = "no"; then + AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no) + fi + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.cat + INSTOBJEXT=.cat + DATADIRNAME=lib + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi]) + fi + fi + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + INTLOBJS="\$(GETTOBJS)" + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_SUBST(MSGFMT) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(AM_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next]) + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + AC_CHECK_FUNCS(stpcpy) + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + AC_DEFINE(HAVE_STPCPY) + fi + + AM_LC_MESSAGES + AM_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl The reference to <locale.h> in the installed <libintl.h> file + dnl must be resolved because we cannot expect the users of this + dnl to define HAVE_LOCALE_H. + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include <locale.h>" + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header <locale.h>. Take care yourself. */" + fi + AC_SUBST(INCLUDE_LOCALE_H) + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + test -d intl || mkdir intl + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed + fi + dnl po2tbl.sed is always needed. + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed + + dnl In the intl/Makefile.in we have a special dependency which makes + dnl only sense for gettext. We comment this out for non-gettext + dnl packages. + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + AC_SUBST(GT_NO) + AC_SUBST(GT_YES) + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl *** For now the libtool support in intl/Makefile is not for real. + l= + AC_SUBST(l) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper <drepper@cygnus.com>, 1996. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in <locale.h>. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES) + fi + fi]) + diff --git a/acm4/gmp.m4 b/acm4/gmp.m4 new file mode 100644 index 00000000..beea42b5 --- /dev/null +++ b/acm4/gmp.m4 @@ -0,0 +1,30 @@ +AC_DEFUN(AM_WITH_GMP, + [AC_MSG_CHECKING(if extended and fractional arithmetic is wanted) + AC_ARG_WITH(gmp, + [ --with-gmp use gmp for extended and fractional arithmetic], + [use_gmp=$withval], [use_gmp=no]) + AC_MSG_RESULT($use_gmp) + + if test "$use_gmp" = yes; then + LIBS="$LIBS -lgmp" + AC_CHECK_HEADER([gmp.h], + [AC_CACHE_CHECK([for mpq_init in libgmp], ac_cv_func_mpq_init_libgmp, + [AC_TRY_LINK([#include <gmp.h>], + [mpq_t x; (void)mpq_init(x)], + ac_cv_func_mpq_init_libgmp=yes, + ac_cv_func_mpq_init_libgmp=no)])], + ac_cv_func_mpq_init_libgmp=no) + + if test "$ac_cv_func_mpq_init_libgmp$ac_cv_header_gmp_h" = yesyes; then + AC_DEFINE(WITH_GMP) + else + LIBS=`echo $LIBS | sed -e 's/-lgmp//'` + AC_MSG_WARN([gmp library not found or does not appear to work]) + use_gmp=no + fi + fi + + if test "$use_gmp" != yes; then + AC_CHECK_SIZEOF(long long int, 0) + fi + ]) diff --git a/acm4/ltdl.m4 b/acm4/ltdl.m4 new file mode 100644 index 00000000..1601efc2 --- /dev/null +++ b/acm4/ltdl.m4 @@ -0,0 +1,429 @@ +## libltdl.m4 - Configure ltdl for the target system. -*-Shell-script-*- +## Copyright (C) 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# serial 1 AC_LIB_LTDL + +AC_DEFUN(AC_LIB_LTDL, +[AC_PREREQ(2.13)dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_C_CONST])dnl +AC_REQUIRE([AC_C_INLINE])dnl + +dnl AC_LIB_LTDL must perform all the checks necessary for compilation +dnl of the ltdl objects -- including compiler checks (above) and header +dnl checks (below). +AC_REQUIRE([AC_HEADER_STDC])dnl + +AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dlfcn.h dl.h dld.h) +AC_CHECK_HEADERS(string.h strings.h, break) +AC_CHECK_FUNCS(strchr index, break) +AC_CHECK_FUNCS(strrchr rindex, break) + +AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl +AC_REQUIRE([AC_LTDL_SHLIBEXT])dnl +AC_REQUIRE([AC_LTDL_SHLIBPATH])dnl +AC_REQUIRE([AC_LTDL_OBJDIR])dnl +AC_REQUIRE([AC_LTDL_DLPREOPEN])dnl +AC_REQUIRE([AC_LTDL_DLLIB])dnl +AC_REQUIRE([AC_LTDL_SYMBOL_USCORE])dnl +]) + +AC_DEFUN(AC_LTDL_ENABLE_INSTALL, +[AC_ARG_ENABLE(ltdl-install, +[ --enable-ltdl-install install libltdl]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) +])]) + + +AC_DEFUN(AC_LTDL_SNARF_CONFIG, +[# Read the libtool configuration +rm -f conftest +./libtool --config > conftest +. ./conftest +rm -f conftest +]) + +AC_DEFUN(AC_LTDL_SHLIBEXT, +[AC_REQUIRE([AC_LTDL_SNARF_CONFIG])dnl +AC_CACHE_CHECK([which extension is used for shared libraries], + libltdl_cv_shlibext, [dnl +( + last= + for spec in $library_names_spec; do + last="$spec" + done +changequote(, ) + echo "$last" | sed 's/\[.*\]//;s/^[^.]*//;s/\$.*$//;s/\.$//' > conftest +changequote([, ]) +) +libltdl_cv_shlibext=`cat conftest` +rm -f conftest +]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED(LTDL_SHLIB_EXT, "$libltdl_cv_shlibext", + [Define to the extension used for shared libraries, say, ".so". ]) +fi +]) + +AC_DEFUN(AC_LTDL_SHLIBPATH, +[AC_REQUIRE([AC_LTDL_SNARF_CONFIG])dnl +AC_CACHE_CHECK([which variable specifies run-time library path], + libltdl_cv_shlibpath_var, [libltdl_cv_shlibpath_var="$shlibpath_var"]) +if test -n "$libltdl_cv_shlibpath_var"; then + AC_DEFINE_UNQUOTED(LTDL_SHLIBPATH_VAR, "$libltdl_cv_shlibpath_var", + [Define to the name of the environment variable that determines the dynamic library search path. ]) +fi +]) + +AC_DEFUN(AC_LTDL_OBJDIR, +[AC_CACHE_CHECK([for objdir], + libltdl_cv_objdir, [libltdl_cv_objdir="$objdir" +if test -n "$objdir"; then + : +else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi +rmdir .libs 2>/dev/null +fi]) +AC_DEFINE_UNQUOTED(LTDL_OBJDIR, "$libltdl_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries. ]) +]) + +AC_DEFUN(AC_LTDL_DLPREOPEN, +[AC_REQUIRE([AC_LTDL_GLOBAL_SYMBOL_PIPE])dnl +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + libltdl_cv_preloaded_symbols, [dnl + if test -n "$global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi +]) +if test x"$libltdl_cv_preloaded_symbols" = x"yes"; then + AC_DEFINE(HAVE_PRELOADED_SYMBOLS, 1, + [Define if libtool can extract symbol lists from object files. ]) +fi +]) + +AC_DEFUN(AC_LTDL_DLLIB, +[LIBADD_DL= +AC_CHECK_LIB(dl, dlopen, [AC_DEFINE(HAVE_LIBDL, 1, + [Define if you have the libdl library or equivalent. ]) LIBADD_DL="-ldl"], +[AC_CHECK_FUNC(dlopen, [AC_DEFINE(HAVE_LIBDL, 1, + [Define if you have the libdl library or equivalent.])])]) +AC_CHECK_FUNC(shl_load, [AC_DEFINE(HAVE_SHL_LOAD, 1, + [Define if you have the shl_load function.])], +[AC_CHECK_LIB(dld, shl_load, + [AC_DEFINE(HAVE_SHL_LOAD, 1, + [Define if you have the shl_load function.]) + LIBADD_DL="$LIBADD_DL -ldld"]) +]) +AC_CHECK_LIB(dld, dld_link, [AC_DEFINE(HAVE_DLD, 1, + [Define if you have the GNU dld library.])dnl +test "x$ac_cv_lib_dld_shl_load" = yes || LIBADD_DL="$LIBADD_DL -ldld"]) +AC_SUBST(LIBADD_DL) + +if test "x$ac_cv_func_dlopen" = xyes || test "x$ac_cv_lib_dl_dlopen" = xyes; then + LIBS_SAVE="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS(dlerror) + LIBS="$LIBS_SAVE" +fi +]) + +AC_DEFUN(AC_LTDL_GLOBAL_SYMBOL_PIPE, +[dnl Check for command to grab the raw symbol name followed +dnl by C symbol name from nm. +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_NM])dnl +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output]) +AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe, +[# These are sane defaults that work on at least a few old systems. +# {They come from Ultrix. What could be older than Ultrix?!! ;)} + +changequote(,)dnl +# Character class describing NM global symbol codes. +ac_symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +ac_symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + ac_symcode='[BCDT]' + ;; +cygwin* | mingw*) + ac_symcode='[ABCDGISTW]' + ;; +hpux*) + ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + ac_symcode='[BCDEGRST]' + ;; +solaris*) + ac_symcode='[BDT]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + ac_symcode='[ABCDGISTW]' +fi +changequote([,])dnl + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($ac_symcode\)[ ][ ]*\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'" + + # Check to see that the pipe works correctly. + ac_pipe_works=no + rm -f conftest.$ac_ext + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func;return 0;} +EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + + if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + + # Try sorting and uniquifying the output. + if sort "$ac_nlist" | uniq > "$ac_nlist"T; then + mv -f "$ac_nlist"T "$ac_nlist" + else + rm -f "$ac_nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then + if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c' + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +changequote(,)dnl +lt_preloaded_symbols[] = +changequote([,])dnl +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + ac_save_LIBS="$LIBS" + ac_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if AC_TRY_EVAL(ac_link) && test -s conftest; then + ac_pipe_works=yes + else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + LIBS="$ac_save_LIBS" + CFLAGS="$ac_save_CFLAGS" + else + echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + else + echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC + fi + else + echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi + else + echo "$progname: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$ac_pipe_works" = yes; then + if test x"$ac_symprfx" = x"_"; then + ac_cv_sys_symbol_underscore=yes + else + ac_cv_sys_symbol_underscore=no + fi + break + else + ac_cv_sys_global_symbol_pipe= + fi +done +]) + +ac_result=yes +if test -z "$ac_cv_sys_global_symbol_pipe"; then + ac_result=no +fi +AC_MSG_RESULT($ac_result) +]) + +AC_DEFUN(AC_LTDL_SYMBOL_USCORE, +[dnl does the compiler prefix global symbols with an underscore? +AC_REQUIRE([AC_LTDL_GLOBAL_SYMBOL_PIPE])dnl +AC_MSG_CHECKING([for _ prefix in compiled symbols]) +AC_CACHE_VAL(ac_cv_sys_symbol_underscore, +[ac_cv_sys_symbol_underscore=no +cat > conftest.$ac_ext <<EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +EOF +if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + fi + else + echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC +fi +rm -rf conftest* +]) +AC_MSG_RESULT($ac_cv_sys_symbol_underscore) +AC_LTDL_DLSYM_USCORE +]) + +AC_DEFUN(AC_LTDL_DLSYM_USCORE, +[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE])dnl +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$ac_cv_func_dlopen" = xyes || + test x"$ac_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + libltdl_cv_need_uscore, [dnl + AC_TRY_RUN([ +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 && !ptr2) { dlclose(self); exit(0); } } exit(1); } +], libltdl_cv_need_uscore=no, libltdl_cv_need_uscore=yes, + libltdl_cv_need_uscore=cross +)]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE(NEED_USCORE, 1, + [Define if dlsym() requires a leading underscode in symbol names. ]) +fi +]) diff --git a/acm4/modules.m4 b/acm4/modules.m4 new file mode 100644 index 00000000..c4a47b76 --- /dev/null +++ b/acm4/modules.m4 @@ -0,0 +1,27 @@ +AC_DEFUN(AM_WITH_MODULES, + [AC_MSG_CHECKING(if support for dynamic modules is wanted) + AC_ARG_WITH(modules, + [ --with-modules add support for dynamic modules], + [use_modules=$withval], [use_modules=no]) + AC_MSG_RESULT($use_modules) + + if test "$use_modules" = yes; then + LIBS="$LIBS -ldl" + AC_CHECK_HEADER([dlfcn.h], + [AC_CACHE_CHECK([for dlopen in libdl], ac_cv_func_dlopen_libdl, + [AC_TRY_LINK([#include <dlfcn.h>], + [(void)dlopen(0, RTLD_NOW)], + ac_cv_func_dlopen_libdl=yes, + ac_cv_func_dlopen_libdl=no)])], + ac_cv_func_dlopen_libdl=no) + + if test "$ac_cv_func_dlopen_libdl$ac_cv_header_dlfcn_h" = yesyes; then + AC_DEFINE(WITH_MODULES) + LDFLAGS="$LDFLAGS -rdynamic" + else + LIBS=`echo $LIBS | sed -e 's/-ldl//'` + AC_MSG_WARN([-ldl library not found or does not appear to work]) + use_modules=no + fi + fi + ]) diff --git a/acm4/regex.m4 b/acm4/regex.m4 new file mode 100644 index 00000000..e5468c65 --- /dev/null +++ b/acm4/regex.m4 @@ -0,0 +1,23 @@ +#serial 2 + +dnl Derived from code in GNU grep. + +AC_DEFUN(jm_WITH_REGEX, + [ + dnl Even packages that don't use regex.c can use this macro. + dnl Of course, for them it doesn't do anything. + + syscmd([test -f lib/regex.c]) + ifelse(sysval, 0, + [ + AC_ARG_WITH(included-regex, + [ --without-included-regex don't compile regex (use with caution)], + jm_with_regex=$withval, + jm_with_regex=yes) + if test "$jm_with_regex" = yes; then + LIBOBJS="$LIBOBJS regex.o" + fi + ], + ) + ] +) diff --git a/c-boxes.el b/c-boxes.el new file mode 100644 index 00000000..c1b80e33 --- /dev/null +++ b/c-boxes.el @@ -0,0 +1,406 @@ +;;; Boxed comments for C mode. +;;; Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. +;;; Francois Pinard <pinard@iro.umontreal.ca>, April 1991. +;;; +;;; I often refill paragraphs inside C comments, while stretching or +;;; shrinking the surrounding box as needed. This is a real pain to +;;; do by hand. Here is the code I made to ease my life on this, +;;; usable from within GNU Emacs. It would not be fair giving all +;;; sources for a product without also giving the means for nicely +;;; modifying them. +;;; +;;; The function rebox-c-comment adjust comment boxes without +;;; refilling comment paragraphs, while reindent-c-comment adjust +;;; comment boxes after refilling. Numeric prefixes are used to add, +;;; remove, or change the style of the box surrounding the comment. +;;; Since refilling paragraphs in C mode does make sense only for +;;; comments, this code redefines the M-q command in C mode. I use +;;; this hack by putting, in my .emacs file: +;;; +;;; (setq c-mode-hook +;;; '(lambda () +;;; (define-key c-mode-map "\M-q" 'reindent-c-comment))) +;;; (autoload 'rebox-c-comment "c-boxes" nil t) +;;; (autoload 'reindent-c-comment "c-boxes" nil t) +;;; +;;; The cursor should be within a comment before any of these +;;; commands, or else it should be between two comments, in which case +;;; the command applies to the next comment. When the command is +;;; given without prefix, the current comment box type is recognized +;;; and preserved. Given 0 as a prefix, the comment box disappears +;;; and the comment stays between a single opening `/*' and a single +;;; closing `*/'. Given 1 or 2 as a prefix, a single or doubled lined +;;; comment box is forced. Given 3 as a prefix, a Taarna style box is +;;; forced, but you do not even want to hear about those. When a +;;; negative prefix is given, the absolute value is used, but the +;;; default style is changed. Any other value (like C-u alone) forces +;;; the default box style. +;;; +;;; I observed rounded corners first in some code from Warren Tucker +;;; <wht@n4hgf.mt-park.ga.us>. + +(defvar c-box-default-style 'single "*Preferred style for box comments.") +(defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.") + +;;; Set or reset the Taarna team's own way for a C style. + +(defun taarna-mode () + (interactive) + (if c-mode-taarna-style + (progn + + (setq c-mode-taarna-style nil) + (setq c-indent-level 2) + (setq c-continued-statement-offset 2) + (setq c-brace-offset 0) + (setq c-argdecl-indent 5) + (setq c-label-offset -2) + (setq c-tab-always-indent t) + (setq c-box-default-style 'single) + (message "C mode: GNU style")) + + (setq c-mode-taarna-style t) + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c-brace-offset -4) + (setq c-argdecl-indent 4) + (setq c-label-offset -4) + (setq c-tab-always-indent t) + (setq c-box-default-style 'taarna) + (message "C mode: Taarna style"))) + +;;; Return the minimum value of the left margin of all lines, or -1 if +;;; all lines are empty. + +(defun buffer-left-margin () + (let ((margin -1)) + (goto-char (point-min)) + (while (not (eobp)) + (skip-chars-forward " \t") + (if (not (looking-at "\n")) + (setq margin + (if (< margin 0) + (current-column) + (min margin (current-column))))) + (forward-line 1)) + margin)) + +;;; Return the maximum value of the right margin of all lines. Any +;;; sentence ending a line has a space guaranteed before the margin. + +(defun buffer-right-margin () + (let ((margin 0) period) + (goto-char (point-min)) + (while (not (eobp)) + (end-of-line) + (if (bobp) + (setq period 0) + (backward-char 1) + (setq period (if (looking-at "[.?!]") 1 0)) + (forward-char 1)) + (setq margin (max margin (+ (current-column) period))) + (forward-char 1)) + margin)) + +;;; Add, delete or adjust a C comment box. If FLAG is nil, the +;;; current boxing style is recognized and preserved. When 0, the box +;;; is removed; when 1, a single lined box is forced; when 2, a double +;;; lined box is forced; when 3, a Taarna style box is forced. If +;;; negative, the absolute value is used, but the default style is +;;; changed. For any other value (like C-u), the default style is +;;; forced. If REFILL is not nil, refill the comment paragraphs prior +;;; to reboxing. + +(defun rebox-c-comment-engine (flag refill) + (save-restriction + (let ((undo-list buffer-undo-list) + (marked-point (point-marker)) + (saved-point (point)) + box-style left-margin right-margin) + + ;; First, find the limits of the block of comments following or + ;; enclosing the cursor, or return an error if the cursor is not + ;; within such a block of comments, narrow the buffer, and + ;; untabify it. + + ;; - insure the point is into the following comment, if any + + (skip-chars-forward " \t\n") + (if (looking-at "/\\*") + (forward-char 2)) + + (let ((here (point)) start end temp) + + ;; - identify a minimal comment block + + (search-backward "/*") + (setq temp (point)) + (beginning-of-line) + (setq start (point)) + (skip-chars-forward " \t") + (if (< (point) temp) + (progn + (goto-char saved-point) + (error "text before comment's start"))) + (search-forward "*/") + (setq temp (point)) + (end-of-line) + (if (looking-at "\n") + (forward-char 1)) + (setq end (point)) + (skip-chars-backward " \t\n") + (if (> (point) temp) + (progn + (goto-char saved-point) + (error "text after comment's end"))) + (if (< end here) + (progn + (goto-char saved-point) + (error "outside any comment block"))) + + ;; - try to extend the comment block backwards + + (goto-char start) + (while (and (not (bobp)) + (progn (previous-line 1) + (beginning-of-line) + (looking-at "[ \t]*/\\*.*\\*/[ \t]*$"))) + (setq start (point))) + + ;; - try to extend the comment block forward + + (goto-char end) + (while (looking-at "[ \t]*/\\*.*\\*/[ \t]*$") + (forward-line 1) + (beginning-of-line) + (setq end (point))) + + ;; - narrow to the whole block of comments + + (narrow-to-region start end)) + + ;; Second, remove all the comment marks, and move all the text + ;; rigidly to the left to insure the left margin stays at the + ;; same place. At the same time, recognize and save the box + ;; style in BOX-STYLE. + + (let ((previous-margin (buffer-left-margin)) + actual-margin) + + ;; - remove all comment marks + + (goto-char (point-min)) + (replace-regexp "^\\([ \t]*\\)/\\*" "\\1 ") + (goto-char (point-min)) + (replace-regexp "^\\([ \t]*\\)|" "\\1 ") + (goto-char (point-min)) + (replace-regexp "\\(\\*/\\||\\)[ \t]*" "") + (goto-char (point-min)) + (replace-regexp "\\*/[ \t]*/\\*" " ") + + ;; - remove the first and last dashed lines + + (setq box-style 'plain) + (goto-char (point-min)) + (if (looking-at "^[ \t]*-*[.\+\\]?[ \t]*\n") + (progn + (setq box-style 'single) + (replace-match "")) + (if (looking-at "^[ \t]*=*[.\+\\]?[ \t]*\n") + (progn + (setq box-style 'double) + (replace-match "")))) + (goto-char (point-max)) + (previous-line 1) + (beginning-of-line) + (if (looking-at "^[ \t]*[`\+\\]?*[-=]+[ \t]*\n") + (progn + (if (eq box-style 'plain) + (setq box-style 'taarna)) + (replace-match ""))) + + ;; - remove all spurious whitespace + + (goto-char (point-min)) + (replace-regexp "[ \t]+$" "") + (goto-char (point-min)) + (if (looking-at "\n+") + (replace-match "")) + (goto-char (point-max)) + (skip-chars-backward "\n") + (if (looking-at "\n\n+") + (replace-match "\n")) + (goto-char (point-min)) + (replace-regexp "\n\n\n+" "\n\n") + + ;; - move the text left is adequate + + (setq actual-margin (buffer-left-margin)) + (if (not (= previous-margin actual-margin)) + (indent-rigidly (point-min) (point-max) + (- previous-margin actual-margin)))) + + ;; Third, select the new box style from the old box style and + ;; the argument, choose the margins for this style and refill + ;; each paragraph. + + ;; - modify box-style only if flag is defined + + (if flag + (setq box-style + (cond ((eq flag 0) 'plain) + ((eq flag 1) 'single) + ((eq flag 2) 'double) + ((eq flag 3) 'taarna) + ((eq flag '-) (setq c-box-default-style 'plain) 'plain) + ((eq flag -1) (setq c-box-default-style 'single) 'single) + ((eq flag -2) (setq c-box-default-style 'double) 'double) + ((eq flag -3) (setq c-box-default-style 'taarna) 'taarna) + (t c-box-default-style)))) + + ;; - compute the left margin + + (setq left-margin (buffer-left-margin)) + + ;; - temporarily set the fill prefix and column, then refill + + (untabify (point-min) (point-max)) + + (if refill + (let ((fill-prefix (make-string left-margin ? )) + (fill-column (- fill-column + (if (memq box-style '(single double)) 4 6)))) + (fill-region (point-min) (point-max)))) + + ;; - compute the right margin after refill + + (setq right-margin (buffer-right-margin)) + + ;; Fourth, put the narrowed buffer back into a comment box, + ;; according to the value of box-style. Values may be: + ;; plain: insert between a single pair of comment delimiters + ;; single: complete box, overline and underline with dashes + ;; double: complete box, overline and underline with equal signs + ;; taarna: comment delimiters on each line, underline with dashes + + ;; - move the right margin to account for left inserts + + (setq right-margin (+ right-margin + (if (memq box-style '(single double)) + 2 + 3))) + + ;; - construct the box comment, from top to bottom + + (goto-char (point-min)) + (cond ((eq box-style 'plain) + + ;; - construct a plain style comment + + (skip-chars-forward " " (+ (point) left-margin)) + (insert (make-string (- left-margin (current-column)) ? ) + "/* ") + (end-of-line) + (forward-char 1) + (while (not (eobp)) + (skip-chars-forward " " (+ (point) left-margin)) + (insert (make-string (- left-margin (current-column)) ? ) + " ") + (end-of-line) + (forward-char 1)) + (backward-char 1) + (insert " */")) + ((eq box-style 'single) + + ;; - construct a single line style comment + + (indent-to left-margin) + (insert "/*") + (insert (make-string (- right-margin (current-column)) ?-) + "-.\n") + (while (not (eobp)) + (skip-chars-forward " " (+ (point) left-margin)) + (insert (make-string (- left-margin (current-column)) ? ) + "| ") + (end-of-line) + (indent-to right-margin) + (insert " |") + (forward-char 1)) + (indent-to left-margin) + (insert "`") + (insert (make-string (- right-margin (current-column)) ?-) + "*/\n")) + ((eq box-style 'double) + + ;; - construct a double line style comment + + (indent-to left-margin) + (insert "/*") + (insert (make-string (- right-margin (current-column)) ?=) + "=\\\n") + (while (not (eobp)) + (skip-chars-forward " " (+ (point) left-margin)) + (insert (make-string (- left-margin (current-column)) ? ) + "| ") + (end-of-line) + (indent-to right-margin) + (insert " |") + (forward-char 1)) + (indent-to left-margin) + (insert "\\") + (insert (make-string (- right-margin (current-column)) ?=) + "*/\n")) + ((eq box-style 'taarna) + + ;; - construct a Taarna style comment + + (while (not (eobp)) + (skip-chars-forward " " (+ (point) left-margin)) + (insert (make-string (- left-margin (current-column)) ? ) + "/* ") + (end-of-line) + (indent-to right-margin) + (insert " */") + (forward-char 1)) + (indent-to left-margin) + (insert "/* ") + (insert (make-string (- right-margin (current-column)) ?-) + " */\n")) + (t (error "unknown box style"))) + + ;; Fifth, retabify, restore the point position, then cleanup the + ;; undo list of any boundary since we started. + + ;; - retabify before left margin only (adapted from tabify.el) + + (goto-char (point-min)) + (while (re-search-forward "^[ \t][ \t][ \t]*" nil t) + (let ((column (current-column)) + (indent-tabs-mode t)) + (delete-region (match-beginning 0) (point)) + (indent-to column))) + + ;; - restore the point position + + (goto-char (marker-position marked-point)) + + ;; - remove all intermediate boundaries from the undo list + + (if (not (eq buffer-undo-list undo-list)) + (let ((cursor buffer-undo-list)) + (while (not (eq (cdr cursor) undo-list)) + (if (car (cdr cursor)) + (setq cursor (cdr cursor)) + (rplacd cursor (cdr (cdr cursor)))))))))) + +;;; Rebox a C comment without refilling it. + +(defun rebox-c-comment (flag) + (interactive "P") + (rebox-c-comment-engine flag nil)) + +;;; Rebox a C comment after refilling. + +(defun reindent-c-comment (flag) + (interactive "P") + (rebox-c-comment-engine flag t)) diff --git a/checks/01.define b/checks/01.define new file mode 100644 index 00000000..7a044c01 --- /dev/null +++ b/checks/01.define @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:939: Origin of test +define(`foo', `Hello world.') +dnl @result{} +foo +dnl @result{}Hello world. diff --git a/checks/02.arguments b/checks/02.arguments new file mode 100644 index 00000000..0d459123 --- /dev/null +++ b/checks/02.arguments @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:963: Origin of test +define(`exch', `$2, $1') +dnl @result{} +exch(arg1, arg2) +dnl @result{}arg2, arg1 diff --git a/checks/02.define b/checks/02.define new file mode 100644 index 00000000..de8bc66d --- /dev/null +++ b/checks/02.define @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:905: Origin of test +define(`array', `defn(format(``array[%d]'', `$1'))') +dnl @result{} +define(`array_set', `define(format(``array[%d]'', `$1'), `$2')') +dnl @result{} +array_set(4, `array element no. 4') +dnl @result{} +array_set(17, `array element no. 17') +dnl @result{} +array(4) +dnl @result{}array element no. 4 +array(eval(10+7)) +dnl @result{}array element no. 17 diff --git a/checks/03.arguments b/checks/03.arguments new file mode 100644 index 00000000..9117964b --- /dev/null +++ b/checks/03.arguments @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:973: Origin of test +define(`exch', `$2, $1') +dnl @result{} +define(exch(``expansion text'', ``macro'')) +dnl @result{} +macro +dnl @result{}expansion text diff --git a/checks/04.arguments b/checks/04.arguments new file mode 100644 index 00000000..8d325ac4 --- /dev/null +++ b/checks/04.arguments @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:993: Origin of test +define(`test', ``Macro name: $0'') +dnl @result{} +test +dnl @result{}Macro name: test diff --git a/checks/05.arguments b/checks/05.arguments new file mode 100644 index 00000000..aaed75e0 --- /dev/null +++ b/checks/05.arguments @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:1003: Origin of test +define(`foo', `This is macro `foo'.') +dnl @result{} +foo +dnl @result{}This is macro foo. diff --git a/checks/06.arguments b/checks/06.arguments new file mode 100644 index 00000000..b866e6c9 --- /dev/null +++ b/checks/06.arguments @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:974: Origin of test +define(`foo', `This is macro `foo'.') +dnl @result{} +foo +dnl @result{}This is macro foo. diff --git a/checks/06.pseudo_argu b/checks/06.pseudo_argu new file mode 100644 index 00000000..8c1f9dfd --- /dev/null +++ b/checks/06.pseudo_argu @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1027: Origin of test +define(`nargs', `$#') +dnl @result{} +nargs +dnl @result{}0 +nargs() +dnl @result{}1 +nargs(arg1, arg2, arg3) +dnl @result{}3 diff --git a/checks/07.pseudo_argu b/checks/07.pseudo_argu new file mode 100644 index 00000000..0517066c --- /dev/null +++ b/checks/07.pseudo_argu @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:1041: Origin of test +define(`echo', `$*') +dnl @result{} +echo(arg1, arg2, arg3 , arg4) +dnl @result{}arg1,arg2,arg3 ,arg4 diff --git a/checks/08.pseudo_argu b/checks/08.pseudo_argu new file mode 100644 index 00000000..8787b016 --- /dev/null +++ b/checks/08.pseudo_argu @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:1052: Origin of test +define(`echo', `$@') +dnl @result{} +echo(arg1, arg2, arg3 , arg4) +dnl @result{}arg1,arg2,arg3 ,arg4 diff --git a/checks/09.pseudo_argu b/checks/09.pseudo_argu new file mode 100644 index 00000000..440d7e7f --- /dev/null +++ b/checks/09.pseudo_argu @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:1062: Origin of test +define(`echo1', `$*') +dnl @result{} +define(`echo2', `$@') +dnl @result{} +define(`foo', `This is macro `foo'.') +dnl @result{} +echo1(foo) +dnl @result{}This is macro This is macro foo.. +echo2(foo) +dnl @result{}This is macro foo. diff --git a/checks/10.pseudo_argu b/checks/10.pseudo_argu new file mode 100644 index 00000000..1842e3ed --- /dev/null +++ b/checks/10.pseudo_argu @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:1082: Origin of test +define(`foo', `$$$ hello $$$') +dnl @result{} +foo +dnl @result{}$$$ hello $$$ diff --git a/checks/11.pseudo_argu b/checks/11.pseudo_argu new file mode 100644 index 00000000..dd46c979 --- /dev/null +++ b/checks/11.pseudo_argu @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:1053: Origin of test +define(`foo', `$$$ hello $$$') +dnl @result{} +foo +dnl @result{}$$$ hello $$$ diff --git a/checks/11.undefine b/checks/11.undefine new file mode 100644 index 00000000..9709263d --- /dev/null +++ b/checks/11.undefine @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:1113: Origin of test +foo +dnl @result{}foo +define(`foo', `expansion text') +dnl @result{} +foo +dnl @result{}expansion text +undefine(`foo') +dnl @result{} +foo +dnl @result{}foo diff --git a/checks/12.defn b/checks/12.defn new file mode 100644 index 00000000..9ebb42da --- /dev/null +++ b/checks/12.defn @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1158: Origin of test +define(`zap', defn(`undefine')) +dnl @result{} +zap(`undefine') +dnl @result{} +undefine(`zap') +dnl @result{}undefine(zap) diff --git a/checks/12.undefine b/checks/12.undefine new file mode 100644 index 00000000..1f61131d --- /dev/null +++ b/checks/12.undefine @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:1084: Origin of test +foo +dnl @result{}foo +define(`foo', `expansion text') +dnl @result{} +foo +dnl @result{}expansion text +undefine(`foo') +dnl @result{} +foo +dnl @result{}foo diff --git a/checks/13.defn b/checks/13.defn new file mode 100644 index 00000000..1deb3f44 --- /dev/null +++ b/checks/13.defn @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1128: Origin of test +define(`zap', defn(`undefine')) +dnl @result{} +zap(`undefine') +dnl @result{} +undefine(`zap') +dnl @result{}undefine(zap) diff --git a/checks/13.pushdef b/checks/13.pushdef new file mode 100644 index 00000000..bdf078ba --- /dev/null +++ b/checks/13.pushdef @@ -0,0 +1,17 @@ +dnl ../doc/m4.texinfo:1204: Origin of test +define(`foo', `Expansion one.') +dnl @result{} +foo +dnl @result{}Expansion one. +pushdef(`foo', `Expansion two.') +dnl @result{} +foo +dnl @result{}Expansion two. +popdef(`foo') +dnl @result{} +foo +dnl @result{}Expansion one. +popdef(`foo') +dnl @result{} +foo +dnl @result{}foo diff --git a/checks/14.defn b/checks/14.defn new file mode 100644 index 00000000..11ece953 --- /dev/null +++ b/checks/14.defn @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1148: Origin of test +define(`string', `The macro dnl is very useful +') +dnl @result{} +string +dnl @result{}The macro +defn(`string') +dnl @result{}The macro dnl is very useful +dnl @result{} diff --git a/checks/14.pushdef b/checks/14.pushdef new file mode 100644 index 00000000..dda7d3fe --- /dev/null +++ b/checks/14.pushdef @@ -0,0 +1,17 @@ +dnl ../doc/m4.texinfo:1228: Origin of test +define(`foo', `Expansion one.') +dnl @result{} +foo +dnl @result{}Expansion one. +pushdef(`foo', `Expansion two.') +dnl @result{} +foo +dnl @result{}Expansion two. +define(`foo', `Second expansion two.') +dnl @result{} +foo +dnl @result{}Second expansion two. +undefine(`foo') +dnl @result{} +foo +dnl @result{}foo diff --git a/checks/15.indir b/checks/15.indir new file mode 100644 index 00000000..881b4deb --- /dev/null +++ b/checks/15.indir @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1272: Origin of test +define(`$$internal$macro', `Internal macro (name `$0')') +dnl @result{} +$$internal$macro +dnl @result{}$$internal$macro +indir(`$$internal$macro') +dnl @result{}Internal macro (name $$internal$macro) diff --git a/checks/15.pushdef b/checks/15.pushdef new file mode 100644 index 00000000..df2859af --- /dev/null +++ b/checks/15.pushdef @@ -0,0 +1,17 @@ +dnl ../doc/m4.texinfo:1192: Origin of test +define(`foo', `Expansion one.') +dnl @result{} +foo +dnl @result{}Expansion one. +pushdef(`foo', `Expansion two.') +dnl @result{} +foo +dnl @result{}Expansion two. +popdef(`foo') +dnl @result{} +foo +dnl @result{}Expansion one. +popdef(`foo') +dnl @result{} +foo +dnl @result{}foo diff --git a/checks/16.ifdef b/checks/16.ifdef new file mode 100644 index 00000000..c4dec7b5 --- /dev/null +++ b/checks/16.ifdef @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1343: Origin of test +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +dnl @result{}foo is not defined +define(`foo', `') +dnl @result{} +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +dnl @result{}foo is defined diff --git a/checks/16.pushdef b/checks/16.pushdef new file mode 100644 index 00000000..48c0cec6 --- /dev/null +++ b/checks/16.pushdef @@ -0,0 +1,17 @@ +dnl ../doc/m4.texinfo:1216: Origin of test +define(`foo', `Expansion one.') +dnl @result{} +foo +dnl @result{}Expansion one. +pushdef(`foo', `Expansion two.') +dnl @result{} +foo +dnl @result{}Expansion two. +define(`foo', `Second expansion two.') +dnl @result{} +foo +dnl @result{}Second expansion two. +undefine(`foo') +dnl @result{} +foo +dnl @result{}foo diff --git a/checks/17.ifelse b/checks/17.ifelse new file mode 100644 index 00000000..836a98f0 --- /dev/null +++ b/checks/17.ifelse @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1381: Origin of test +ifelse(foo, bar, `true') +dnl @result{} +ifelse(foo, foo, `true') +dnl @result{}true +ifelse(foo, bar, `true', `false') +dnl @result{}false +ifelse(foo, foo, `true', `false') +dnl @result{}true diff --git a/checks/17.indir b/checks/17.indir new file mode 100644 index 00000000..d573a386 --- /dev/null +++ b/checks/17.indir @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1267: Origin of test +define(`$$internal$macro', `Internal macro (name `$0')') +dnl @result{} +$$internal$macro +dnl @result{}$$internal$macro +indir(`$$internal$macro') +dnl @result{}Internal macro (name $$internal$macro) diff --git a/checks/18.ifdef b/checks/18.ifdef new file mode 100644 index 00000000..40c355ca --- /dev/null +++ b/checks/18.ifdef @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1338: Origin of test +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +dnl @result{}foo is not defined +define(`foo', `') +dnl @result{} +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +dnl @result{}foo is defined diff --git a/checks/18.ifelse b/checks/18.ifelse new file mode 100644 index 00000000..ddfb7fbb --- /dev/null +++ b/checks/18.ifelse @@ -0,0 +1,3 @@ +dnl ../doc/m4.texinfo:1400: Origin of test +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +dnl @result{}seventh diff --git a/checks/19.ifelse b/checks/19.ifelse new file mode 100644 index 00000000..0886f6db --- /dev/null +++ b/checks/19.ifelse @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1376: Origin of test +ifelse(`foo', `bar', `true') +dnl @result{} +ifelse(`foo', `foo', `true') +dnl @result{}true +ifelse(`foo', `bar', `true', `false') +dnl @result{}false +ifelse(`foo', `foo', `true', `false') +dnl @result{}true diff --git a/checks/19.loops b/checks/19.loops new file mode 100644 index 00000000..8ac68eb9 --- /dev/null +++ b/checks/19.loops @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:1437: Origin of test +shift(bar) +dnl @result{} +shift(foo, bar, baz) +dnl @result{}bar,baz diff --git a/checks/20.ifelse b/checks/20.ifelse new file mode 100644 index 00000000..aff53225 --- /dev/null +++ b/checks/20.ifelse @@ -0,0 +1,3 @@ +dnl ../doc/m4.texinfo:1395: Origin of test +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +dnl @result{}seventh diff --git a/checks/20.loops b/checks/20.loops new file mode 100644 index 00000000..55dfc86c --- /dev/null +++ b/checks/20.loops @@ -0,0 +1,10 @@ +dnl ../doc/m4.texinfo:1447: Origin of test +define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', + `reverse(shift($@)), `$1'')') +dnl @result{} +reverse +dnl @result{} +reverse(foo) +dnl @result{}foo +reverse(foo, bar, gnats, and gnus) +dnl @result{}and gnus, gnats, bar, foo diff --git a/checks/21.dumpdef b/checks/21.dumpdef new file mode 100644 index 00000000..689bb786 --- /dev/null +++ b/checks/21.dumpdef @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1561: Origin of test +define(`foo', `Hello world.') +dnl @result{} +dumpdef(`foo') +dnl @error{}foo: `Hello world.' +dnl @result{} +dumpdef(`define') +dnl @error{}define: <define> +dnl @result{} diff --git a/checks/21.loops b/checks/21.loops new file mode 100644 index 00000000..2b0290b1 --- /dev/null +++ b/checks/21.loops @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1432: Origin of test +shift +dnl @result{} +shift(bar) +dnl @result{} +shift(foo, bar, baz) +dnl @result{}bar,baz diff --git a/checks/22.loops b/checks/22.loops new file mode 100644 index 00000000..1ecdc076 --- /dev/null +++ b/checks/22.loops @@ -0,0 +1,10 @@ +dnl ../doc/m4.texinfo:1444: Origin of test +define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', + `reverse(shift($@)), `$1'')') +dnl @result{} +reverse +dnl @result{} +reverse(foo) +dnl @result{}foo +reverse(foo, bar, gnats, and gnus) +dnl @result{}and gnus, gnats, bar, foo diff --git a/checks/22.trace b/checks/22.trace new file mode 100644 index 00000000..ae4e639c --- /dev/null +++ b/checks/22.trace @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:1606: Origin of test +define(`foo', `Hello World.') +dnl @result{} +define(`echo', `$@') +dnl @result{} +traceon(`foo', `echo') +dnl @result{} +foo +dnl @error{}m4trace: -1- foo -> `Hello World.' +dnl @result{}Hello World. +echo(gnus, and gnats) +dnl @error{}m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' +dnl @result{}gnus,and gnats diff --git a/checks/23.dnl b/checks/23.dnl new file mode 100644 index 00000000..763d9843 --- /dev/null +++ b/checks/23.dnl @@ -0,0 +1,4 @@ +dnl ../doc/m4.texinfo:1757: Origin of test +define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. +foo +dnl @result{}Macro foo. diff --git a/checks/23.dumpdef b/checks/23.dumpdef new file mode 100644 index 00000000..c65f6934 --- /dev/null +++ b/checks/23.dumpdef @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1558: Origin of test +define(`foo', `Hello world.') +dnl @result{} +dumpdef(`foo') +dnl @error{}foo: `Hello world.' +dnl @result{} +dumpdef(`define') +dnl @error{}define: <define> +dnl @result{} diff --git a/checks/24.changequote b/checks/24.changequote new file mode 100644 index 00000000..c74dafdf --- /dev/null +++ b/checks/24.changequote @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1795: Origin of test +changequote([, ]) +dnl @result{} +define([foo], [Macro [foo].]) +dnl @result{} +foo +dnl @result{}Macro foo. diff --git a/checks/24.trace b/checks/24.trace new file mode 100644 index 00000000..491eef27 --- /dev/null +++ b/checks/24.trace @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:1603: Origin of test +define(`foo', `Hello World.') +dnl @result{} +define(`echo', `$@') +dnl @result{} +traceon(`foo', `echo') +dnl @result{} +foo +dnl @error{}m4trace: -1- foo -> `Hello World.' +dnl @result{}Hello World. +echo(gnus, and gnats) +dnl @error{}m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' +dnl @result{}gnus,and gnats diff --git a/checks/25.changequote b/checks/25.changequote new file mode 100644 index 00000000..b3976016 --- /dev/null +++ b/checks/25.changequote @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1807: Origin of test +changequote([[, ]]) +dnl @result{} +define([[foo]], [[Macro [[[foo]]].]]) +dnl @result{} +foo +dnl @result{}Macro [foo]. diff --git a/checks/25.dnl b/checks/25.dnl new file mode 100644 index 00000000..ecdb9b24 --- /dev/null +++ b/checks/25.dnl @@ -0,0 +1,4 @@ +dnl ../doc/m4.texinfo:1755: Origin of test +define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. +foo +dnl @result{}Macro foo. diff --git a/checks/26.changequote b/checks/26.changequote new file mode 100644 index 00000000..2187982b --- /dev/null +++ b/checks/26.changequote @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1819: Origin of test +define(`foo', `Macro `FOO'.') +dnl @result{} +changequote(, ) +dnl @result{} +foo +dnl @result{}Macro `FOO'. +`foo' +dnl @result{}`Macro `FOO'.' diff --git a/checks/27.changecom b/checks/27.changecom new file mode 100644 index 00000000..108cbb59 --- /dev/null +++ b/checks/27.changecom @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:1859: Origin of test +define(`comment', `COMMENT') +dnl @result{} +# A normal comment +dnl @result{}# A normal comment +changecom(`/*', `*/') +dnl @result{} +# Not a comment anymore +dnl @result{}# Not a COMMENT anymore +But: /* this is a comment now */ while this is not a comment +dnl @result{}But: /* this is a comment now */ while this is not a COMMENT diff --git a/checks/27.changequote b/checks/27.changequote new file mode 100644 index 00000000..bd71cb96 --- /dev/null +++ b/checks/27.changequote @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1805: Origin of test +changequote([[, ]]) +dnl @result{} +define([[foo]], [[Macro [[[foo]]].]]) +dnl @result{} +foo +dnl @result{}Macro [foo]. diff --git a/checks/28.changecom b/checks/28.changecom new file mode 100644 index 00000000..35604dee --- /dev/null +++ b/checks/28.changecom @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1880: Origin of test +define(`comment', `COMMENT') +dnl @result{} +changecom +dnl @result{} +# Not a comment anymore +dnl @result{}# Not a COMMENT anymore diff --git a/checks/28.changequote b/checks/28.changequote new file mode 100644 index 00000000..ed067f50 --- /dev/null +++ b/checks/28.changequote @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:1817: Origin of test +define(`foo', `Macro `FOO'.') +dnl @result{} +changequote(, ) +dnl @result{} +foo +dnl @result{}Macro `FOO'. +`foo' +dnl @result{}`Macro `FOO'.' diff --git a/checks/29.changecom b/checks/29.changecom new file mode 100644 index 00000000..7a1dfa60 --- /dev/null +++ b/checks/29.changecom @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:1857: Origin of test +define(`comment', `COMMENT') +dnl @result{} +# A normal comment +dnl @result{}# A normal comment +changecom(`/*', `*/') +dnl @result{} +# Not a comment anymore +dnl @result{}# Not a COMMENT anymore +But: /* this is a comment now */ while this is not a comment +dnl @result{}But: /* this is a comment now */ while this is not a COMMENT diff --git a/checks/29.m4wrap b/checks/29.m4wrap new file mode 100644 index 00000000..b303c56c --- /dev/null +++ b/checks/29.m4wrap @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2019: Origin of test +define(`cleanup', `This is the `cleanup' actions. +') +dnl @result{} +m4wrap(`cleanup') +dnl @result{} +This is the first and last normal input line. +dnl @result{}This is the first and last normal input line. +dnl @result{}This is the cleanup actions. diff --git a/checks/30.changecom b/checks/30.changecom new file mode 100644 index 00000000..fce2579c --- /dev/null +++ b/checks/30.changecom @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:1878: Origin of test +define(`comment', `COMMENT') +dnl @result{} +changecom +dnl @result{} +# Not a comment anymore +dnl @result{}# Not a COMMENT anymore diff --git a/checks/30.include b/checks/30.include new file mode 100644 index 00000000..85968c80 --- /dev/null +++ b/checks/30.include @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:2078: Origin of test +include(`no-such-file') +dnl @result{} +dnl @error{}30.include:2: m4: Cannot open no-such-file: No such file or directory +sinclude(`no-such-file') +dnl @result{} diff --git a/checks/31.changesynta b/checks/31.changesynta new file mode 100644 index 00000000..02f0ac23 --- /dev/null +++ b/checks/31.changesynta @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2023: Origin of test +define(`test.1', `TEST ONE') +dnl @result{} +__file__ +dnl @result{}31.changesynta +changesyntax(`O_', `W.') +dnl @result{} +__file__ +dnl @result{}__file__ +test.1 +dnl @result{}TEST ONE diff --git a/checks/31.include b/checks/31.include new file mode 100644 index 00000000..1d3e01bc --- /dev/null +++ b/checks/31.include @@ -0,0 +1,8 @@ +dnl ../doc/m4.texinfo:2098: Origin of test +define(`foo', `FOO') +dnl @result{} +include(`incl.m4') +dnl @result{}Include file start +dnl @result{}FOO +dnl @result{}Include file end +dnl @result{} diff --git a/checks/32.changesynta b/checks/32.changesynta new file mode 100644 index 00000000..8bd2f388 --- /dev/null +++ b/checks/32.changesynta @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2039: Origin of test +define(`test', `$#') +dnl @result{} +test(a, b, c) +dnl @result{}3 +changesyntax(`(<', `,|', `)>', `O(,)') +dnl @result{} +test(a, b, c) +dnl @result{}0(a, b, c) +test<a|b|c> +dnl @result{}3 diff --git a/checks/32.include b/checks/32.include new file mode 100644 index 00000000..ba3208f5 --- /dev/null +++ b/checks/32.include @@ -0,0 +1,8 @@ +dnl ../doc/m4.texinfo:2113: Origin of test +define(`bar', include(`incl.m4')) +dnl @result{} +This is `bar': >>>bar<<< +dnl @result{}This is bar: >>>Include file start +dnl @result{}foo +dnl @result{}Include file end +dnl @result{}<<< diff --git a/checks/33.changesynta b/checks/33.changesynta new file mode 100644 index 00000000..e4f76f71 --- /dev/null +++ b/checks/33.changesynta @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2056: Origin of test +define(`test', `$1$2$3') +dnl @result{} +test(a, b, c) +dnl @result{}abc +changesyntax(`O ') +dnl @result{} +test(a, b, c) +dnl @result{}a b c diff --git a/checks/33.divert b/checks/33.divert new file mode 100644 index 00000000..1f90fa5f --- /dev/null +++ b/checks/33.divert @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2201: Origin of test +divert(1) +This text is diverted. +divert +dnl @result{} +This text is not diverted. +dnl @result{}This text is not diverted. +dnl @result{} +dnl @result{}This text is diverted. diff --git a/checks/34.changesynta b/checks/34.changesynta new file mode 100644 index 00000000..7b430d69 --- /dev/null +++ b/checks/34.changesynta @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2075: Origin of test +define(`@', `TEST') +dnl @result{} +@ +dnl @result{}@ +changesyntax(`A@') +dnl @result{} +@ +dnl @result{}TEST diff --git a/checks/34.divert b/checks/34.divert new file mode 100644 index 00000000..6f0a8a78 --- /dev/null +++ b/checks/34.divert @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:2221: Origin of test +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +dnl @result{} diff --git a/checks/35.changesynta b/checks/35.changesynta new file mode 100644 index 00000000..d2ab2d3f --- /dev/null +++ b/checks/35.changesynta @@ -0,0 +1,15 @@ +dnl ../doc/m4.texinfo:2099: Origin of test +define(`test', `TEST') +dnl @result{} +changesyntax(`L<', `R>') +dnl @result{} +<test> +dnl @result{}test +`test> +dnl @result{}test +changequote(<[>, `]') +dnl @result{} +<test> +dnl @result{}<TEST> +[test] +dnl @result{}test diff --git a/checks/35.undivert b/checks/35.undivert new file mode 100644 index 00000000..a67dce3c --- /dev/null +++ b/checks/35.undivert @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2252: Origin of test +divert(1) +This text is diverted. +divert +dnl @result{} +This text is not diverted. +dnl @result{}This text is not diverted. +undivert(1) +dnl @result{} +dnl @result{}This text is diverted. +dnl @result{} diff --git a/checks/36.changesynta b/checks/36.changesynta new file mode 100644 index 00000000..db3f46f2 --- /dev/null +++ b/checks/36.changesynta @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2121: Origin of test +changesyntax(`({<', `)}>', `,;:', `O(,)') +dnl @result{} +eval{2**4-1; 2 : 8> +dnl @result{}00001111 diff --git a/checks/36.undivert b/checks/36.undivert new file mode 100644 index 00000000..59e2741d --- /dev/null +++ b/checks/36.undivert @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:2276: Origin of test +divert(1) +This text is diverted first. +divert(0)undivert(1)dnl +dnl @result{} +dnl @result{}This text is diverted first. +undivert(1) +dnl @result{} +divert(1) +This text is also diverted but not appended. +divert(0)undivert(1)dnl +dnl @result{} +dnl @result{}This text is also diverted but not appended. diff --git a/checks/37.changesynta b/checks/37.changesynta new file mode 100644 index 00000000..378d6d51 --- /dev/null +++ b/checks/37.changesynta @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:2132: Origin of test +define(`test', `==$1==') +dnl @result{} +changequote(`<<', `>>') +dnl @result{} +changesyntax(<<L[>>, <<R]>>) +dnl @result{} +test(<<testing]>>) +dnl @result{}==testing]== +test([testing>>]) +dnl @result{}==testing>>== +test([<<testing>>]) +dnl @result{}==<<testing>>== diff --git a/checks/37.undivert b/checks/37.undivert new file mode 100644 index 00000000..98a11953 --- /dev/null +++ b/checks/37.undivert @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2302: Origin of test +define(`bar', `BAR') +dnl @result{} +undivert(`foo') +dnl @result{}bar +dnl @result{} +include(`foo') +dnl @result{}BAR +dnl @result{} diff --git a/checks/38.divnum b/checks/38.divnum new file mode 100644 index 00000000..e56346ee --- /dev/null +++ b/checks/38.divnum @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:2328: Origin of test +Initial divnum +dnl @result{}Initial 0 +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +dnl @result{} +dnl @result{} +dnl @result{}Diversion one: 1 +dnl @result{} +dnl @result{}Diversion two: 2 diff --git a/checks/38.m4wrap b/checks/38.m4wrap new file mode 100644 index 00000000..95fb12dd --- /dev/null +++ b/checks/38.m4wrap @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2293: Origin of test +define(`cleanup', `This is the `cleanup' actions. +') +dnl @result{} +m4wrap(`cleanup') +dnl @result{} +This is the first and last normal input line. +dnl @result{}This is the first and last normal input line. +dnl @result{}This is the cleanup actions. diff --git a/checks/39.cleardiv b/checks/39.cleardiv new file mode 100644 index 00000000..ab3176b7 --- /dev/null +++ b/checks/39.cleardiv @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:2359: Origin of test +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert(-1) +undivert diff --git a/checks/39.include b/checks/39.include new file mode 100644 index 00000000..68cba854 --- /dev/null +++ b/checks/39.include @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:2352: Origin of test +include(`no-such-file') +dnl @result{} +dnl @error{}39.include:2: m4: Cannot open no-such-file: No such file or directory +sinclude(`no-such-file') +dnl @result{} diff --git a/checks/40.cleardiv b/checks/40.cleardiv new file mode 100644 index 00000000..9d095038 --- /dev/null +++ b/checks/40.cleardiv @@ -0,0 +1,4 @@ +dnl ../doc/m4.texinfo:2374: Origin of test +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') +dnl @result{} diff --git a/checks/40.include b/checks/40.include new file mode 100644 index 00000000..1afae8e2 --- /dev/null +++ b/checks/40.include @@ -0,0 +1,8 @@ +dnl ../doc/m4.texinfo:2372: Origin of test +define(`foo', `FOO') +dnl @result{} +include(`incl.m4') +dnl @result{}Include file start +dnl @result{}FOO +dnl @result{}Include file end +dnl @result{} diff --git a/checks/41.include b/checks/41.include new file mode 100644 index 00000000..e5965be9 --- /dev/null +++ b/checks/41.include @@ -0,0 +1,8 @@ +dnl ../doc/m4.texinfo:2387: Origin of test +define(`bar', include(`incl.m4')) +dnl @result{} +This is `bar': >>>bar<<< +dnl @result{}This is bar: >>>Include file start +dnl @result{}foo +dnl @result{}Include file end +dnl @result{}<<< diff --git a/checks/41.len b/checks/41.len new file mode 100644 index 00000000..1c64b8e4 --- /dev/null +++ b/checks/41.len @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2416: Origin of test +len() +dnl @result{}0 +len(`abcdef') +dnl @result{}6 diff --git a/checks/42.divert b/checks/42.divert new file mode 100644 index 00000000..9c86c5de --- /dev/null +++ b/checks/42.divert @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2478: Origin of test +divert(1) +This text is diverted. +divert +dnl @result{} +This text is not diverted. +dnl @result{}This text is not diverted. +dnl @result{} +dnl @result{}This text is diverted. diff --git a/checks/42.index b/checks/42.index new file mode 100644 index 00000000..bac694f7 --- /dev/null +++ b/checks/42.index @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2442: Origin of test +index(`gnus, gnats, and armadillos', `nat') +dnl @result{}7 +index(`gnus, gnats, and armadillos', `dag') +dnl @result{}-1 diff --git a/checks/43.divert b/checks/43.divert new file mode 100644 index 00000000..252fc982 --- /dev/null +++ b/checks/43.divert @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:2498: Origin of test +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +dnl @result{} diff --git a/checks/43.regexp b/checks/43.regexp new file mode 100644 index 00000000..3ea5cac3 --- /dev/null +++ b/checks/43.regexp @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2474: Origin of test +regexp(`GNUs not Unix', `\<[a-z]\w+') +dnl @result{}5 +regexp(`GNUs not Unix', `\<Q\w*') +dnl @result{}-1 diff --git a/checks/44.regexp b/checks/44.regexp new file mode 100644 index 00000000..8636b787 --- /dev/null +++ b/checks/44.regexp @@ -0,0 +1,3 @@ +dnl ../doc/m4.texinfo:2486: Origin of test +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +dnl @result{}*** Unix *** nix *** diff --git a/checks/44.undivert b/checks/44.undivert new file mode 100644 index 00000000..f99162c6 --- /dev/null +++ b/checks/44.undivert @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2529: Origin of test +divert(1) +This text is diverted. +divert +dnl @result{} +This text is not diverted. +dnl @result{}This text is not diverted. +undivert(1) +dnl @result{} +dnl @result{}This text is diverted. +dnl @result{} diff --git a/checks/45.substr b/checks/45.substr new file mode 100644 index 00000000..a60c791b --- /dev/null +++ b/checks/45.substr @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2512: Origin of test +substr(`gnus, gnats, and armadillos', 6) +dnl @result{}gnats, and armadillos +substr(`gnus, gnats, and armadillos', 6, 5) +dnl @result{}gnats diff --git a/checks/45.undivert b/checks/45.undivert new file mode 100644 index 00000000..8835f78e --- /dev/null +++ b/checks/45.undivert @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:2553: Origin of test +divert(1) +This text is diverted first. +divert(0)undivert(1)dnl +dnl @result{} +dnl @result{}This text is diverted first. +undivert(1) +dnl @result{} +divert(1) +This text is also diverted but not appended. +divert(0)undivert(1)dnl +dnl @result{} +dnl @result{}This text is also diverted but not appended. diff --git a/checks/46.translit b/checks/46.translit new file mode 100644 index 00000000..78c10daa --- /dev/null +++ b/checks/46.translit @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:2553: Origin of test +translit(`GNUs not Unix', `A-Z') +dnl @result{}s not nix +translit(`GNUs not Unix', `a-z', `A-Z') +dnl @result{}GNUS NOT UNIX +translit(`GNUs not Unix', `A-Z', `z-a') +dnl @result{}tmfs not fnix diff --git a/checks/46.undivert b/checks/46.undivert new file mode 100644 index 00000000..f951d011 --- /dev/null +++ b/checks/46.undivert @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2579: Origin of test +define(`bar', `BAR') +dnl @result{} +undivert(`foo') +dnl @result{}bar +dnl @result{} +include(`foo') +dnl @result{}BAR +dnl @result{} diff --git a/checks/47.divnum b/checks/47.divnum new file mode 100644 index 00000000..c64945f8 --- /dev/null +++ b/checks/47.divnum @@ -0,0 +1,13 @@ +dnl ../doc/m4.texinfo:2605: Origin of test +Initial divnum +dnl @result{}Initial 0 +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +dnl @result{} +dnl @result{} +dnl @result{}Diversion one: 1 +dnl @result{} +dnl @result{}Diversion two: 2 diff --git a/checks/47.patsubst b/checks/47.patsubst new file mode 100644 index 00000000..8235b50c --- /dev/null +++ b/checks/47.patsubst @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2604: Origin of test +patsubst(`GNUs not Unix', `^', `OBS: ') +dnl @result{}OBS: GNUs not Unix +patsubst(`GNUs not Unix', `\<', `OBS: ') +dnl @result{}OBS: GNUs OBS: not OBS: Unix +patsubst(`GNUs not Unix', `\w*', `(\&)') +dnl @result{}(GNUs)() (not)() (Unix) +patsubst(`GNUs not Unix', `\w+', `(\&)') +dnl @result{}(GNUs) (not) (Unix) +patsubst(`GNUs not Unix', `[A-Z][a-z]+') +dnl @result{}GN not diff --git a/checks/48.cleardiv b/checks/48.cleardiv new file mode 100644 index 00000000..cd779109 --- /dev/null +++ b/checks/48.cleardiv @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:2636: Origin of test +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert(-1) +undivert diff --git a/checks/48.patsubst b/checks/48.patsubst new file mode 100644 index 00000000..0e042a62 --- /dev/null +++ b/checks/48.patsubst @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2621: Origin of test +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') +dnl @result{}Gnus Not Unix diff --git a/checks/49.cleardiv b/checks/49.cleardiv new file mode 100644 index 00000000..8d4b7501 --- /dev/null +++ b/checks/49.cleardiv @@ -0,0 +1,4 @@ +dnl ../doc/m4.texinfo:2651: Origin of test +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') +dnl @result{} diff --git a/checks/49.format b/checks/49.format new file mode 100644 index 00000000..0daa49a7 --- /dev/null +++ b/checks/49.format @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2656: Origin of test +define(`foo', `The brown fox jumped over the lazy dog') +dnl @result{} +format(`The string "%s" is %d characters long', foo, len(foo)) +dnl @result{}The string "The brown fox jumped over the lazy dog" is 38 characters long diff --git a/checks/50.incr b/checks/50.incr new file mode 100644 index 00000000..45ee7226 --- /dev/null +++ b/checks/50.incr @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2726: Origin of test +incr(4) +dnl @result{}5 +decr(7) +dnl @result{}6 diff --git a/checks/50.len b/checks/50.len new file mode 100644 index 00000000..37c7cf72 --- /dev/null +++ b/checks/50.len @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2693: Origin of test +len() +dnl @result{}0 +len(`abcdef') +dnl @result{}6 diff --git a/checks/51.eval b/checks/51.eval new file mode 100644 index 00000000..dcf04759 --- /dev/null +++ b/checks/51.eval @@ -0,0 +1,18 @@ +dnl ../doc/m4.texinfo:2808: Origin of test +eval(-3 * 5) +dnl @result{}-15 +eval(index(`Hello world', `llo') >= 0) +dnl @result{}1 +define(`square', `eval(($1)**2)') +dnl @result{} +square(9) +dnl @result{}81 +square(square(5)+1) +dnl @result{}676 +define(`foo', `666') +dnl @result{} +eval(`foo'/6) +dnl @error{}51.eval:14: m4: Bad expression in eval: foo/6 +dnl @result{} +eval(foo/6) +dnl @result{}111 diff --git a/checks/51.index b/checks/51.index new file mode 100644 index 00000000..e540cdd8 --- /dev/null +++ b/checks/51.index @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2719: Origin of test +index(`gnus, gnats, and armadillos', `nat') +dnl @result{}7 +index(`gnus, gnats, and armadillos', `dag') +dnl @result{}-1 diff --git a/checks/52.eval b/checks/52.eval new file mode 100644 index 00000000..b6a0da83 --- /dev/null +++ b/checks/52.eval @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2839: Origin of test +eval(666, 10) +dnl @result{}666 +eval(666, 11) +dnl @result{}556 +eval(666, 6) +dnl @result{}3030 +eval(666, 6, 10) +dnl @result{}0000003030 +eval(-666, 6, 10) +dnl @result{}-000003030 diff --git a/checks/52.regexp b/checks/52.regexp new file mode 100644 index 00000000..27ad63d5 --- /dev/null +++ b/checks/52.regexp @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2751: Origin of test +regexp(`GNUs not Unix', `\<[a-z]\w+') +dnl @result{}5 +regexp(`GNUs not Unix', `\<Q\w*') +dnl @result{}-1 diff --git a/checks/53.esyscmd b/checks/53.esyscmd new file mode 100644 index 00000000..c92f7941 --- /dev/null +++ b/checks/53.esyscmd @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:2924: Origin of test +define(`vice', `esyscmd(grep Vice ../COPYING)') +dnl @result{} +vice +dnl @result{} Ty Coon, President of Vice +dnl @result{} diff --git a/checks/53.regexp b/checks/53.regexp new file mode 100644 index 00000000..b9263838 --- /dev/null +++ b/checks/53.regexp @@ -0,0 +1,3 @@ +dnl ../doc/m4.texinfo:2763: Origin of test +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +dnl @result{}*** Unix *** nix *** diff --git a/checks/54.substr b/checks/54.substr new file mode 100644 index 00000000..b2ad41ff --- /dev/null +++ b/checks/54.substr @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2789: Origin of test +substr(`gnus, gnats, and armadillos', 6) +dnl @result{}gnats, and armadillos +substr(`gnus, gnats, and armadillos', 6, 5) +dnl @result{}gnats diff --git a/checks/54.sysval b/checks/54.sysval new file mode 100644 index 00000000..bc9400db --- /dev/null +++ b/checks/54.sysval @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2955: Origin of test +syscmd(`false') +dnl @result{} +ifelse(sysval, 0, zero, non-zero) +dnl @result{}non-zero +syscmd(`true') +dnl @result{} +sysval +dnl @result{}0 diff --git a/checks/55.errprint b/checks/55.errprint new file mode 100644 index 00000000..ba292c22 --- /dev/null +++ b/checks/55.errprint @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:3034: Origin of test +errprint(`Illegal arguments to forloop +') +dnl @error{}Illegal arguments to forloop +dnl @result{} diff --git a/checks/55.translit b/checks/55.translit new file mode 100644 index 00000000..d0c1a522 --- /dev/null +++ b/checks/55.translit @@ -0,0 +1,7 @@ +dnl ../doc/m4.texinfo:2830: Origin of test +translit(`GNUs not Unix', `A-Z') +dnl @result{}s not nix +translit(`GNUs not Unix', `a-z', `A-Z') +dnl @result{}GNUS NOT UNIX +translit(`GNUs not Unix', `A-Z', `z-a') +dnl @result{}tmfs not fnix diff --git a/checks/56.errprint b/checks/56.errprint new file mode 100644 index 00000000..a5be31ff --- /dev/null +++ b/checks/56.errprint @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:3059: Origin of test +errprint(`m4:'__file__:__line__: `Input error +') +dnl @error{}m4:56.errprint:2: Input error +dnl @result{} diff --git a/checks/56.patsubst b/checks/56.patsubst new file mode 100644 index 00000000..5da8e3c7 --- /dev/null +++ b/checks/56.patsubst @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:2881: Origin of test +patsubst(`GNUs not Unix', `^', `OBS: ') +dnl @result{}OBS: GNUs not Unix +patsubst(`GNUs not Unix', `\<', `OBS: ') +dnl @result{}OBS: GNUs OBS: not OBS: Unix +patsubst(`GNUs not Unix', `\w*', `(\&)') +dnl @result{}(GNUs)() (not)() (Unix) +patsubst(`GNUs not Unix', `\w+', `(\&)') +dnl @result{}(GNUs) (not) (Unix) +patsubst(`GNUs not Unix', `[A-Z][a-z]+') +dnl @result{}GN not diff --git a/checks/57.m4exit b/checks/57.m4exit new file mode 100644 index 00000000..2cbb2d18 --- /dev/null +++ b/checks/57.m4exit @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:3082: Origin of test +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +dnl @result{} +fatal_error(`This is a BAD one, buster') +dnl @error{}m4: 57.m4exit: 5: fatal error: This is a BAD one, buster diff --git a/checks/57.patsubst b/checks/57.patsubst new file mode 100644 index 00000000..36f0f315 --- /dev/null +++ b/checks/57.patsubst @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:2898: Origin of test +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') +dnl @result{}Gnus Not Unix diff --git a/checks/58.format b/checks/58.format new file mode 100644 index 00000000..edeefd7e --- /dev/null +++ b/checks/58.format @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:2933: Origin of test +define(`foo', `The brown fox jumped over the lazy dog') +dnl @result{} +format(`The string "%s" is %d characters long', foo, len(foo)) +dnl @result{}The string "The brown fox jumped over the lazy dog" is 38 characters long diff --git a/checks/59.incr b/checks/59.incr new file mode 100644 index 00000000..a6c4f6f2 --- /dev/null +++ b/checks/59.incr @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:3003: Origin of test +incr(4) +dnl @result{}5 +decr(7) +dnl @result{}6 diff --git a/checks/60.eval b/checks/60.eval new file mode 100644 index 00000000..89490b2e --- /dev/null +++ b/checks/60.eval @@ -0,0 +1,18 @@ +dnl ../doc/m4.texinfo:3097: Origin of test +eval(-3 * 5) +dnl @result{}-15 +eval(index(`Hello world', `llo') >= 0) +dnl @result{}1 +define(`square', `eval(($1)**2)') +dnl @result{} +square(9) +dnl @result{}81 +square(square(5)+1) +dnl @result{}676 +define(`foo', `666') +dnl @result{} +eval(`foo'/6) +dnl @error{}60.eval:14: m4: Bad expression in eval: foo/6 +dnl @result{} +eval(foo/6) +dnl @result{}111 diff --git a/checks/61.eval b/checks/61.eval new file mode 100644 index 00000000..64594c57 --- /dev/null +++ b/checks/61.eval @@ -0,0 +1,11 @@ +dnl ../doc/m4.texinfo:3128: Origin of test +eval(666, 10) +dnl @result{}666 +eval(666, 11) +dnl @result{}556 +eval(666, 6) +dnl @result{}3030 +eval(666, 6, 10) +dnl @result{}0000003030 +eval(-666, 6, 10) +dnl @result{}-000003030 diff --git a/checks/62.esyscmd b/checks/62.esyscmd new file mode 100644 index 00000000..27c3bda4 --- /dev/null +++ b/checks/62.esyscmd @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:3213: Origin of test +define(`vice', `esyscmd(grep Vice ../COPYING)') +dnl @result{} +vice +dnl @result{} Ty Coon, President of Vice +dnl @result{} diff --git a/checks/63.sysval b/checks/63.sysval new file mode 100644 index 00000000..1b7b110a --- /dev/null +++ b/checks/63.sysval @@ -0,0 +1,9 @@ +dnl ../doc/m4.texinfo:3244: Origin of test +syscmd(`false') +dnl @result{} +ifelse(sysval, 0, zero, non-zero) +dnl @result{}non-zero +syscmd(`true') +dnl @result{} +sysval +dnl @result{}0 diff --git a/checks/64.errprint b/checks/64.errprint new file mode 100644 index 00000000..b0cfbffd --- /dev/null +++ b/checks/64.errprint @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:3324: Origin of test +errprint(`Illegal arguments to forloop +') +dnl @error{}Illegal arguments to forloop +dnl @result{} diff --git a/checks/65.errprint b/checks/65.errprint new file mode 100644 index 00000000..230093e8 --- /dev/null +++ b/checks/65.errprint @@ -0,0 +1,5 @@ +dnl ../doc/m4.texinfo:3349: Origin of test +errprint(`m4:'__file__:__line__: `Input error +') +dnl @error{}m4:65.errprint:2: Input error +dnl @result{} diff --git a/checks/66.m4exit b/checks/66.m4exit new file mode 100644 index 00000000..eccef14b --- /dev/null +++ b/checks/66.m4exit @@ -0,0 +1,6 @@ +dnl ../doc/m4.texinfo:3372: Origin of test +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +dnl @result{} +fatal_error(`This is a BAD one, buster') +dnl @error{}m4: 66.m4exit: 5: fatal error: This is a BAD one, buster diff --git a/checks/Makefile.am b/checks/Makefile.am new file mode 100644 index 00000000..65d0de77 --- /dev/null +++ b/checks/Makefile.am @@ -0,0 +1,16 @@ +EXTRA_DIST = check-them foo get-them incl.m4 stamp-checks $(CHECKS) + +CHECKS = ??.* + +all: stamp-checks + +stamp-checks: get-them ../doc/m4.texinfo + rm -f $(srcdir)/$(CHECKS) + cd $(srcdir) && AWK=$(AWK) ./get-them ../doc/m4.texinfo + touch $(srcdir)/stamp-checks + +check: stamp-checks + PATH=`pwd`/../src:$$PATH; export PATH; \ + cd $(srcdir) && ./check-them $(CHECKS) + + diff --git a/checks/Makefile.in b/checks/Makefile.in new file mode 100644 index 00000000..c1c4aaf8 --- /dev/null +++ b/checks/Makefile.in @@ -0,0 +1,76 @@ +# Makefile for GNU m4 checks directory. +# Copyright (C) 1992, 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +PRODUCT = @PRODUCT@ +VERSION = @VERSION@ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +# Should be GNU awk, for the get-them script. +AWK = @AWK@ + +# Vern says that the first star is required around an Alpha make bug. +CHECKS = *[0-9][0-9].* +DISTFILES = Makefile.in get-them check-them stamp-checks incl.m4 foo + +all: stamp-checks + +stamp-checks: get-them ../doc/m4.texinfo + rm -f $(srcdir)/$(CHECKS) + cd $(srcdir) && AWK=$(AWK) ./get-them ../doc/m4.texinfo + touch $(srcdir)/stamp-checks + +install: + +uninstall: + +check: stamp-checks + PATH=`pwd`/../src:$$PATH; export PATH; \ + cd $(srcdir) && ./check-them $(CHECKS) + +tags: + +mostlyclean: + +clean: mostlyclean + +distclean: clean + rm -f Makefile + +realclean: distclean + rm -f $(CHECKS) stamp-checks + +dist: $(DISTFILES) + @echo "Copying distribution files" + @for file in $(DISTFILES); do \ + ln $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/checks 2> /dev/null \ + || cp -p $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/checks; \ + done + @for file in $(srcdir)/$(CHECKS); do \ + ln $$file ../$(PRODUCT)-$(VERSION)/checks \ + || cp -p $$file ../$(PRODUCT)-$(VERSION)/checks; \ + done + +Makefile: Makefile.in ../config.status + cd .. && CONFIG_FILES=checks/$@ CONFIG_HEADERS= ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/checks/check-them b/checks/check-them new file mode 100755 index 00000000..5dd205b9 --- /dev/null +++ b/checks/check-them @@ -0,0 +1,51 @@ +#!/bin/sh +# Check GNU m4 against examples from the manual source. +# Copyright (C) 1992 Free Software Foundation, Inc. + +out=/tmp/m4-out.$$ +err=/tmp/m4-err.$$ +xout=/tmp/m4-xout.$$ +xerr=/tmp/m4-xerr.$$ + +trap "rm -f $out $err $xout $xerr; exit 1" 1 2 15 + +m4 --version + +for file +do + echo "Checking $file" + m4 -d $file >$out 2>$err + + sed -e '/^dnl @result{}/!d' -e 's///' $file > $xout + + if cmp -s $out $xout; then + : + else + failed="$failed $file:out" + echo `sed -e 's/^dnl //' -e 1q $file` + echo "$file: stdout mismatch" + diff $xout $out + fi + + sed -e '/^dnl @error{}/!d' -e 's///' $file > $xerr + + if cmp -s $err $xerr; then + : + else + failed="$failed $file:err" + echo `sed -e 's/^dnl //' -e 1q $file` + echo "$file: stderr mismatch" + diff $xerr $err + fi + +done + +rm -f $out $err $xout $xerr + +echo +if test -z "$failed"; then + echo "All checks successful" +else + echo "Failed checks were:" + echo " $failed" +fi diff --git a/checks/foo b/checks/foo new file mode 100644 index 00000000..5716ca59 --- /dev/null +++ b/checks/foo @@ -0,0 +1 @@ +bar diff --git a/checks/get-them b/checks/get-them new file mode 100755 index 00000000..84300f02 --- /dev/null +++ b/checks/get-them @@ -0,0 +1,68 @@ +#!/bin/sh +# Extract all examples from the manual source. +# Copyright (C) 1992 Free Software Foundation, Inc. + +# This script is for use with GNU awk. + +FILE=${1-/dev/null} + +$AWK ' + +BEGIN { + node = ""; + seq = -1; + count = 0; + file = "NONE"; +} + +/^@node / { + if (seq > 0) + printf(" -- %d file%s", seq, seq == 1 ? "" : "s"); + if (seq >= 0) + printf("\n"); + + split($0, tmp, ","); + node = substr(tmp[1], 7); + if (length(node) > 11) + printf("Node: %s - truncated", node); + else + printf("Node: %s ", node); + gsub(" ", "_", node); + node = tolower(substr(node, 1, 11)); + seq = 0; +} + +/^@comment ignore$/ { + getline; + next; +} + +/^@example$/, /^@end example$/ { + if (seq < 0) + next; + if ($0 ~ /^@example$/) { + if (count > 0) + close (file); + seq++; + count++; + file = sprintf("%02d.%s", count, node); + printf("dnl %s:%d: Origin of test\n", FILENAME, NR) > file; + next; + } + if ($0 ~ /^@end example$/) { + next; + } + if ($0 ~ /^\^D$/) + next; + if ($0 ~ /^@result\{\}/ || $0 ~ /^@error\{\}/) + prefix = "dnl "; + else + prefix = ""; + gsub("@@", "@", $0); + printf("%s%s\n", prefix, $0) >> file; +} + +END { + printf("\n"); +} +' $FILE diff --git a/checks/incl.m4 b/checks/incl.m4 new file mode 100644 index 00000000..ab9572eb --- /dev/null +++ b/checks/incl.m4 @@ -0,0 +1,3 @@ +Include file start +foo +Include file end diff --git a/checks/stamp-checks b/checks/stamp-checks new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/checks/stamp-checks diff --git a/config.guess b/config.guess new file mode 100755 index 00000000..413ed41c --- /dev/null +++ b/config.guess @@ -0,0 +1,883 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# Written by Per Bothner <bothner@cygnus.com>. +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <<EOF >dummy.s + .globl main + .ent main +main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + ${CC-cc} dummy.s -o dummy 2>/dev/null + if test "$?" = 0 ; then + ./dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + fi + rm -f dummy.s dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:*|MIS*:OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >dummy.c + int main (argc, argv) int argc; char **argv; { + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + ${CC-cc} dummy.c -o dummy \ + && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[3478]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo i386-pc-cygwin32 + exit 0 ;; + i*:MINGW*:*) + echo i386-pc-mingw32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin32 + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=`ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; + i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; + sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + sed 's/^ //' <<EOF >dummy.s + .globl main + .ent main + main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + LIBC="" + ${CC-cc} dummy.s -o dummy 2>/dev/null + if test "$?" = 0 ; then + ./dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + + objdump --private-headers dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f dummy.s dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >dummy.c <<EOF +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >dummy.c <<EOF +#include <features.h> +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..c3e44e7e --- /dev/null +++ b/config.h.in @@ -0,0 +1,129 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define 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 + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* 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 if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you don't have vprintf but do have _doprnt. */ +#undef HAVE_DOPRNT + +/* Define if you have the vprintf function. */ +#undef HAVE_VPRINTF + +/* Define if on MINIX. */ +#undef _MINIX + +/* Define if the system does not provide POSIX.1 features except + with this defined. */ +#undef _POSIX_1_SOURCE + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +#undef size_t + +/* 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 run-time. + 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 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if the changeword(REGEXP) functionnality is wanted. */ +#undef ENABLE_CHANGEWORD + +/* Define to 1 if you have ecvt(3), fcvt(3) and gcvt(3), define to 2 if + these are declared in <stdlib.h>. */ +#undef HAVE_EFGCVT + +/* Define to 1 if #include <signal.h> declares struct sigcontext */ +#undef HAVE_SIGCONTEXT + +/* Define to the name of the distribution. */ +#undef PRODUCT + +/* Define to 1 if ANSI function prototypes are usable. */ +#undef PROTOTYPES + +/* Define to int if rlim_t is not defined in sys/resource.h */ +#undef rlim_t + +/* Define to struct sigaltstack if stack_t is not defined in sys/signal.h */ +#undef stack_t + +/* Define to 1 if using stack overflow detection. */ +#undef USE_STACKOVF + +/* Define to the version of the distribution. */ +#undef VERSION + +/* Define to 1 for better use of the debugging malloc library. See + site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz. */ +#undef WITH_DMALLOC + +/* Define if you have the ecvt function. */ +#undef HAVE_ECVT + +/* Define if you have the mkstemp function. */ +#undef HAVE_MKSTEMP + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the sigaltstack function. */ +#undef HAVE_SIGALTSTACK + +/* Define if you have the sigstack function. */ +#undef HAVE_SIGSTACK + +/* Define if you have the sigvec function. */ +#undef HAVE_SIGVEC + +/* Define if you have the strerror function. */ +#undef HAVE_STRERROR + +/* Define if you have the tmpfile function. */ +#undef HAVE_TMPFILE + +/* Define if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the <siginfo.h> header file. */ +#undef HAVE_SIGINFO_H + +/* Define if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H diff --git a/config.sub b/config.sub new file mode 100755 index 00000000..213a6d47 --- /dev/null +++ b/config.sub @@ -0,0 +1,954 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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. + +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) + os= + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 \ + | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \ + | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ + | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ + | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ + | mipstx39 | mipstx39el \ + | sparc | sparclet | sparclite | sparc64 | v850) + basic_machine=$basic_machine-unknown + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[3456]86) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + vax-* | tahoe-* | i[3456]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ + | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \ + | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ + | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mipstx39-* | mipstx39el-* \ + | f301-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[3456]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[3456]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[3456]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[3456]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + np1) + basic_machine=np1-gould + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5) + basic_machine=i586-intel + ;; + pentiumpro | p6) + basic_machine=i686-intel + ;; + pentium-* | p5-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + k5) + # We don't have specific support for AMD's K5 yet, so just call it a Pentium + basic_machine=i586-amd + ;; + nexen) + # We don't have specific support for Nexgen yet, so just call it a Pentium + basic_machine=i586-nexgen + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -xenix) + os=-xenix + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-semi) + os=-aout + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-ibm) + os=-aix + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f301-fujitsu) + os=-uxpv + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/configure b/configure new file mode 100755 index 00000000..b8658a69 --- /dev/null +++ b/configure @@ -0,0 +1,2123 @@ +#!/bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.1 +# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-changeword enable -W and changeword() builtin" +ac_help="$ac_help + --with-dmalloc use dmalloc, as in dmalloc.tar.gz from + @/ftp.antaire.com:antaire/src/dmalloc." + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE + +# Initialize some other variables. +subdirs= + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -build | --build | --buil | --bui | --bu | --b) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=PREFIX install architecture-dependent files in PREFIX + [same as prefix] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +--enable and --with options recognized:$ac_help +EOF + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.1" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 unused; standard input +# 1 file creation +# 2 errors and warnings +# 3 unused; some systems may open it to /dev/tty +# 4 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 4>/dev/null +else + exec 4>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=src/m4.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} $CFLAGS $CPPFLAGS conftest.$ac_ext -c 1>&5 2>&5' +ac_link='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext -o conftest $LIBS 1>&5 2>&5' + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. + echo 's,\\,\\\\,g; s,\$,$$,g' > conftestsed + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + + +PRODUCT=m4 +VERSION=1.4 +cat >> confdefs.h <<EOF +#define PRODUCT "$PRODUCT" +EOF + +cat >> confdefs.h <<EOF +#define VERSION "$VERSION" +EOF + + + + +for ac_prog in mawk gawk nawk awk +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_prog_AWK'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AWK="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AWK="$ac_cv_prog_AWK" +if test -n "$AWK"; then + echo "$ac_t""$AWK" 1>&4 +else + echo "$ac_t""no" 1>&4 +fi + +test -n "$AWK" && break +done + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&4 +else + echo "$ac_t""no" 1>&4 +fi + + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi +echo "$ac_t""$ac_cv_prog_gcc" 1>&4 +if test $ac_cv_prog_gcc = yes; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_prog_gcc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_gcc_g=yes +else + ac_cv_prog_gcc_g=no +fi +rm -f conftest* + +fi + echo "$ac_t""$ac_cv_prog_gcc_g" 1>&4 + if test $ac_cv_prog_gcc_g = yes; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&4 +if test -z "$INSTALL"; then +if eval "test \"`echo '${'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + case "$ac_dir" in + ''|.|/etc|/usr/sbin|/usr/etc|/sbin|/usr/afsws/bin|/usr/ucb) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_ifs" + # As a last resort, use the slow shell script. + test -z "$ac_cv_path_install" && ac_cv_path_install="$ac_install_sh" +fi + INSTALL="$ac_cv_path_install" +fi +echo "$ac_t""$INSTALL" 1>&4 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether ${MAKE-make} sets \$MAKE""... $ac_c" 1>&4 +set dummy ${MAKE-make}; ac_make=$2 +if eval "test \"`echo '${'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&4 + SET_MAKE= +else + echo "$ac_t""no" 1>&4 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&4 +else + echo "$ac_t""no" 1>&4 +fi + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&4 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '${'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 683 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 697 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi +fi +CPP="$ac_cv_prog_CPP" +echo "$ac_t""$CPP" 1>&4 + +echo $ac_n "checking for AIX""... $ac_c" 1>&4 +cat > conftest.$ac_ext <<EOF +#line 722 "configure" +#include "confdefs.h" +#ifdef _AIX + yes +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + echo "$ac_t""yes" 1>&4; cat >> confdefs.h <<\EOF +#define _ALL_SOURCE 1 +EOF + +else + rm -rf conftest* + echo "$ac_t""no" 1>&4 +fi +rm -f conftest* + + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&4 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&4 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&4 + ISC= +fi + +ac_safe=`echo "minix/config.h" | tr './\055' '___'` +echo $ac_n "checking for minix/config.h""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 769 "configure" +#include "confdefs.h" +#include <minix/config.h> +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&4 + MINIX=yes +else + echo "$ac_t""no" 1>&4 +MINIX= +fi + +if test "$MINIX" = yes; then + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + cat >> confdefs.h <<\EOF +#define _POSIX_1_SOURCE 2 +EOF + + cat >> confdefs.h <<\EOF +#define _MINIX 1 +EOF + +fi + +echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_prog_cc_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + ac_cv_prog_cc_stdc=no +ac_save_CFLAGS="$CFLAGS" +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX -Aa -D_HPUX_SOURCE +# SVR4 -Xc +for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc +do + CFLAGS="$ac_save_CFLAGS $ac_arg" + cat > conftest.$ac_ext <<EOF +#line 824 "configure" +#include "confdefs.h" +#if !defined(__STDC__) || __STDC__ != 1 +choke me +#endif + +int main() { return 0; } +int t() { +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + ac_cv_prog_cc_stdc="$ac_arg"; break +fi +rm -f conftest* + +done +CFLAGS="$ac_save_CFLAGS" + +fi + +echo "$ac_t""$ac_cv_prog_cc_stdc" 1>&4 +case "x$ac_cv_prog_cc_stdc" in + x|xno) ;; + *) CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + + +echo $ac_n "checking for function prototypes""... $ac_c" 1>&4 +if test "$ac_cv_prog_cc_stdc" != no; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define PROTOTYPES 1 +EOF + + U= ANSI2KNR= +else + echo "$ac_t""no" 1>&4 + U=_ ANSI2KNR=ansi2knr +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 873 "configure" +#include "confdefs.h" + +int main() { return 0; } +int t() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + ac_cv_c_const=yes +else + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_c_const" 1>&4 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + + +for ac_hdr in limits.h memory.h siginfo.h string.h unistd.h +do +ac_safe=`echo "$ac_hdr" | tr './\055' '___'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 950 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&4 + ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&4 +fi +done + +# If we cannot run a trivial program, we must be cross compiling. +echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_c_cross'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + if test "$cross_compiling" = yes; then + ac_cv_cross=yes +else +cat > conftest.$ac_ext <<EOF +#line 987 "configure" +#include "confdefs.h" +main(){return(0);} +EOF +eval $ac_link +if test -s conftest && (./conftest; exit) 2>/dev/null; then + ac_cv_c_cross=no +else + ac_cv_c_cross=yes +fi +fi +rm -fr conftest* +fi +cross_compiling=$ac_cv_c_cross +echo "$ac_t""$ac_cv_c_cross" 1>&4 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1008 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1030 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1048 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + ac_cv_header_stdc=no +else +cat > conftest.$ac_ext <<EOF +#line 1069 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +eval $ac_link +if test -s conftest && (./conftest; exit) 2>/dev/null; then + : +else + ac_cv_header_stdc=no +fi +fi +rm -fr conftest* +fi +fi +echo "$ac_t""$ac_cv_header_stdc" 1>&4 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1103 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <signal.h> +#ifdef signal +#undef signal +#endif +extern void (*signal ()) (); +int main() { return 0; } +int t() { +int i; +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + ac_cv_type_signal=void +else + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_signal" 1>&4 +cat >> confdefs.h <<EOF +#define RETSIGTYPE $ac_cv_type_signal +EOF + + +echo $ac_n "checking for size_t""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1137 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&4 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + + +for ac_func in mkstemp sigaction sigaltstack sigstack sigvec strerror tmpfile +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1171 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&4 + ac_tr_func=HAVE_`echo $ac_func | tr '[a-z]' '[A-Z]'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&4 +fi +done + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1220 "configure" +#include "confdefs.h" +#include <alloca.h> +int main() { return 0; } +int t() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_header_alloca_h" 1>&4 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_alloca'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1251 "configure" +#include "confdefs.h" + +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +#endif + +int main() { return 0; } +int t() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + ac_cv_func_alloca=yes +else + rm -rf conftest* + ac_cv_func_alloca=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_func_alloca" 1>&4 +if test $ac_cv_func_alloca = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.o + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1309 "configure" +#include "confdefs.h" +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_os_cray" 1>&4 +if test $ac_cv_os_cray = yes; then +echo $ac_n "checking for _getb67""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func__getb67'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1336 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char _getb67(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__getb67) || defined (__stub____getb67) +choke me +#else +_getb67(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func__getb67=yes" +else + rm -rf conftest* + eval "ac_cv_func__getb67=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'_getb67`\" = yes"; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define CRAY_STACKSEG_END _getb67 +EOF + +else + echo "$ac_t""no" 1>&4 +echo $ac_n "checking for GETB67""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_GETB67'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1379 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char GETB67(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_GETB67) || defined (__stub___GETB67) +choke me +#else +GETB67(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func_GETB67=yes" +else + rm -rf conftest* + eval "ac_cv_func_GETB67=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'GETB67`\" = yes"; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define CRAY_STACKSEG_END GETB67 +EOF + +else + echo "$ac_t""no" 1>&4 +echo $ac_n "checking for getb67""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_getb67'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1422 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char getb67(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getb67) || defined (__stub___getb67) +choke me +#else +getb67(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func_getb67=yes" +else + rm -rf conftest* + eval "ac_cv_func_getb67=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'getb67`\" = yes"; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define CRAY_STACKSEG_END getb67 +EOF + +else + echo "$ac_t""no" 1>&4 +fi + +fi + +fi + +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else +cat > conftest.$ac_ext <<EOF +#line 1476 "configure" +#include "confdefs.h" +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +eval $ac_link +if test -s conftest && (./conftest; exit) 2>/dev/null; then + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +fi +fi +rm -fr conftest* +fi +echo "$ac_t""$ac_cv_c_stack_direction" 1>&4 +cat >> confdefs.h <<EOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +EOF + +fi + +echo $ac_n "checking for vprintf""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_vprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1516 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char vprintf(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_vprintf) || defined (__stub___vprintf) +choke me +#else +vprintf(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func_vprintf=yes" +else + rm -rf conftest* + eval "ac_cv_func_vprintf=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define HAVE_VPRINTF 1 +EOF + +else + echo "$ac_t""no" 1>&4 +fi + +if test "$ac_cv_func_vprintf" != yes; then +echo $ac_n "checking for _doprnt""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func__doprnt'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1562 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char _doprnt(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__doprnt) || defined (__stub____doprnt) +choke me +#else +_doprnt(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func__doprnt=yes" +else + rm -rf conftest* + eval "ac_cv_func__doprnt=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define HAVE_DOPRNT 1 +EOF + +else + echo "$ac_t""no" 1>&4 +fi + +fi + +for ac_func in strtol +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1611 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&4 + : +else + echo "$ac_t""no" 1>&4 +LIBOBJS="$LIBOBJS ${ac_func}.o" +fi + +done + +echo $ac_n "checking ecvt declaration""... $ac_c" 1>&4 +cat > conftest.$ac_ext <<EOF +#line 1653 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "ecvt" >/dev/null 2>&1; then + rm -rf conftest* + echo "$ac_t""yes" 1>&4; cat >> confdefs.h <<\EOF +#define HAVE_EFGCVT 2 +EOF + +else + rm -rf conftest* + echo "$ac_t""no" 1>&4; for ac_func in ecvt +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&4 +if eval "test \"`echo '${'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&4 +else + cat > conftest.$ac_ext <<EOF +#line 1673 "configure" +#include "confdefs.h" +#include <ctype.h> /* Arbitrary system header to define __stub macros. */ +/* Override any gcc2 internal prototype to avoid an error. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&4 + ac_tr_func=HAVE_`echo $ac_func | tr '[a-z]' '[A-Z]'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&4 +fi +done + +fi +rm -f conftest* + + +echo $ac_n "checking if stack overflow is detectable""... $ac_c" 1>&4 +# Code from Jim Avera <jima@netcom.com>. +# stackovf.c requires: +# 1. Either sigaction with SA_ONSTACK, or sigvec with SV_ONSTACK +# 2. Either sigaltstack or sigstack +# 3. getrlimit, including support for RLIMIT_STACK +use_stackovf=no +if test "$ac_cv_func_sigaction" = yes || test "$ac_cv_func_sigvec" = yes; then + if test "$ac_cv_func_sigaltstack" = yes || test "$ac_cv_func_sigstack" = yes; then + cat > conftest.$ac_ext <<EOF +#line 1729 "configure" +#include "confdefs.h" +#include <sys/time.h> +#include <sys/resource.h> +#include <signal.h> +int main() { return 0; } +int t() { +struct rlimit r; int i; getrlimit (RLIMIT_STACK, &r) +#if (!defined(HAVE_SIGACTION) || !defined(SA_ONSTACK)) \ + && (!defined(HAVE_SIGVEC) || !defined(SV_ONSTACK)) +choke me /* SA_ONSTACK and/or SV_ONSTACK are not defined */ +#endif +; return 0; } +EOF +if eval $ac_link; then + rm -rf conftest* + use_stackovf=yes +fi +rm -f conftest* + + fi +fi +echo "$ac_t""$use_stackovf" 1>&4 +if test "$use_stackovf" = yes; then + cat >> confdefs.h <<\EOF +#define USE_STACKOVF 1 +EOF + + STACKOVF=stackovf.${U}o + + cat > conftest.$ac_ext <<EOF +#line 1760 "configure" +#include "confdefs.h" +#include <sys/resource.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "rlim_t" >/dev/null 2>&1; then + : +else + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define rlim_t int +EOF + +fi +rm -f conftest* + + cat > conftest.$ac_ext <<EOF +#line 1777 "configure" +#include "confdefs.h" +#include <signal.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "stack_t" >/dev/null 2>&1; then + : +else + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define stack_t struct sigaltstack +EOF + +fi +rm -f conftest* + + cat > conftest.$ac_ext <<EOF +#line 1794 "configure" +#include "confdefs.h" +#include <signal.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "sigcontext" >/dev/null 2>&1; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_SIGCONTEXT 1 +EOF + +fi +rm -f conftest* + +fi + +echo $ac_n "checking if changeword is wanted""... $ac_c" 1>&4 +# Check whether --enable-changeword or --disable-changeword was given. +enableval="$enable_changeword" +if test -n "$enableval"; then + if test "$enableval" = yes; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define ENABLE_CHANGEWORD 1 +EOF + +else + echo "$ac_t""no" 1>&4 +fi +else + echo "$ac_t""no" 1>&4 +fi + + +echo $ac_n "checking if malloc debugging is wanted""... $ac_c" 1>&4 +# Check whether --with-dmalloc or --without-dmalloc was given. +withval="$with_dmalloc" +if test -n "$withval"; then + if test "$withval" = yes; then + echo "$ac_t""yes" 1>&4 + cat >> confdefs.h <<\EOF +#define WITH_DMALLOC 1 +EOF + + LIBS="$LIBS -ldmalloc" + LDFLAGS="$LDFLAGS -g" +else + echo "$ac_t""no" 1>&4 +fi +else + echo "$ac_t""no" 1>&4 +fi + + +trap '' 1 2 15 +if test -w $cache_file; then +echo "updating cache $cache_file" +cat > $cache_file <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# Ultrix sh set writes to stderr and can't be redirected directly. +(set) 2>&1 | + sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/: \${\1='\2'}/p" \ + >> $cache_file +else +echo "not updating unwritable cache $cache_file" +fi + +trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#!/bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.1" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr Makefile doc/Makefile lib/Makefile src/Makefile \ +checks/Makefile examples/Makefile config.h conftest*; exit 1' 1 2 15 + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@PRODUCT@%$PRODUCT%g +s%@VERSION@%$VERSION%g +s%@AWK@%$AWK%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@SET_MAKE@%$SET_MAKE%g +s%@RANLIB@%$RANLIB%g +s%@CPP@%$CPP%g +s%@U@%$U%g +s%@ANSI2KNR@%$ANSI2KNR%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBOBJS@%$LIBOBJS%g +s%@STACKOVF@%$STACKOVF%g + +CEOF +EOF +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile lib/Makefile src/Makefile \ +checks/Makefile examples/Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust relative srcdir, etc. for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/$ac_dir" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file +fi; done +rm -f conftest.subs + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"} +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + cp $ac_given_srcdir/$ac_file_in conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. +# Maximum number of lines to put in a single here document. +ac_max_here_lines=12 + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + + +test -z "$CONFIG_HEADERS" || date > stamp-h +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..4db026fa --- /dev/null +++ b/configure.in @@ -0,0 +1,88 @@ +# Configure template for GNU m4. +# Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. +# Process this file with autoconf to produce a configure script. + +undefine([changeword]) + +AC_INIT(src/m4.c) +AC_CONFIG_HEADER(config.h) +AC_ARG_PROGRAM + +PRODUCT=m4 +VERSION=1.4 +AC_DEFINE_UNQUOTED(PRODUCT, "$PRODUCT") +AC_DEFINE_UNQUOTED(VERSION, "$VERSION") +AC_SUBST(PRODUCT) +AC_SUBST(VERSION) + +AC_PROG_AWK +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_PROG_RANLIB + +AC_AIX +AC_ISC_POSIX +AC_MINIX +fp_C_PROTOTYPES +AC_C_CONST + +AC_CHECK_HEADERS(limits.h memory.h siginfo.h string.h unistd.h) +AC_HEADER_STDC +AC_TYPE_SIGNAL +AC_TYPE_SIZE_T + +AC_CHECK_FUNCS(mkstemp sigaction sigaltstack sigstack sigvec strerror tmpfile) +AC_FUNC_ALLOCA +AC_FUNC_VPRINTF +AC_REPLACE_FUNCS(strtol) +AC_MSG_CHECKING(ecvt declaration) +AC_EGREP_HEADER(ecvt, stdlib.h, + [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_EFGCVT, 2)], + [AC_MSG_RESULT(no); AC_CHECK_FUNCS(ecvt)]) + +AC_MSG_CHECKING(if stack overflow is detectable) +# Code from Jim Avera <jima@netcom.com>. +# stackovf.c requires: +# 1. Either sigaction with SA_ONSTACK, or sigvec with SV_ONSTACK +# 2. Either sigaltstack or sigstack +# 3. getrlimit, including support for RLIMIT_STACK +use_stackovf=no +if test "$ac_cv_func_sigaction" = yes || test "$ac_cv_func_sigvec" = yes; then + if test "$ac_cv_func_sigaltstack" = yes || test "$ac_cv_func_sigstack" = yes; then + AC_TRY_LINK([#include <sys/time.h> +#include <sys/resource.h> +#include <signal.h>], + [struct rlimit r; int i; getrlimit (RLIMIT_STACK, &r) +#if (!defined(HAVE_SIGACTION) || !defined(SA_ONSTACK)) \ + && (!defined(HAVE_SIGVEC) || !defined(SV_ONSTACK)) +choke me /* SA_ONSTACK and/or SV_ONSTACK are not defined */ +#endif], + use_stackovf=yes) + fi +fi +AC_MSG_RESULT($use_stackovf) +if test "$use_stackovf" = yes; then + AC_DEFINE(USE_STACKOVF) + STACKOVF=stackovf.${U}o + AC_SUBST(STACKOVF) + AC_EGREP_HEADER(rlim_t, sys/resource.h, , AC_DEFINE(rlim_t, int)) + AC_EGREP_HEADER(stack_t, signal.h, , AC_DEFINE(stack_t, struct sigaltstack)) + AC_EGREP_HEADER(sigcontext, signal.h, AC_DEFINE(HAVE_SIGCONTEXT)) +fi + +AC_MSG_CHECKING(if changeword is wanted) +AC_ARG_ENABLE(changeword, +[ --enable-changeword enable -W and changeword() builtin], +[if test "$enableval" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(ENABLE_CHANGEWORD) +else + AC_MSG_RESULT(no) +fi], [AC_MSG_RESULT(no)]) + +fp_WITH_DMALLOC + +AC_OUTPUT(Makefile doc/Makefile lib/Makefile src/Makefile \ +checks/Makefile examples/Makefile, +[test -z "$CONFIG_HEADERS" || date > stamp-h]) diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..ff3bdaf9 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1 @@ +info_TEXINFOS = m4.texinfo diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 00000000..d0e15763 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,92 @@ +# Makefile for GNU m4 documentation. +# Copyright (C) 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +PRODUCT = @PRODUCT@ +VERSION = @VERSION@ + +SHELL = /bin/sh +srcdir = @srcdir@ +VPATH = @srcdir@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi + +prefix = @prefix@ +infodir = $(prefix)/info + +.SUFFIXES: + +DISTFILES = Makefile.in m4.texinfo texinfo.tex \ +stamp-vti version.texi m4.info m4.info-1 m4.info-2 m4.info-3 + +all: m4.info + +info: m4.info + +m4.info: m4.texinfo version.texi + cd $(srcdir) && $(MAKEINFO) m4.texinfo + +dvi: m4.dvi + +m4.dvi: m4.texinfo version.texi + $(TEXI2DVI) $(srcdir)/m4.texinfo + +version.texi: stamp-vti +stamp-vti: m4.texinfo ../configure.in + echo "@set EDITION $(VERSION)" > version.tmp + echo "@set UPDATED `date '+%B %Y'`" >> version.tmp + echo "@set VERSION $(VERSION)" >> version.tmp + if cmp -s version.tmp $(srcdir)/version.texi; then rm version.tmp; \ + else mv version.tmp $(srcdir)/version.texi; fi + date > $(srcdir)/stamp-vti + +install: all + $(srcdir)/../mkinstalldirs $(infodir) + cd $(srcdir) && for file in m4.info*; do \ + $(INSTALL_DATA) $$file $(infodir)/$$file; \ + done + +uninstall: + rm -f $(infodir)/m4.info* + +mostlyclean: + rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.log *.pg *.toc *.tp *.vr + rm -f *.tmp + +clean: mostlyclean + +distclean: clean + rm -f Makefile + +realclean: distclean + rm -f stamp-vti version.texi m4.info* + +dist: $(DISTFILES) + @echo "Copying distribution files" + @for file in $(DISTFILES); do \ + ln $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/doc 2> /dev/null \ + || cp -p $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/doc; \ + done + +Makefile: ../config.status Makefile.in + cd .. && CONFIG_FILES=doc/$@ CONFIG_HEADERS= ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/helptoman.pl b/doc/helptoman.pl new file mode 100644 index 00000000..f0039978 --- /dev/null +++ b/doc/helptoman.pl @@ -0,0 +1,249 @@ +#!/usr/bin/perl -w + +# Generate a short man page from --help and --version output. +# Copyright 1997, 98 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. + +require 5.003; + +use strict; +use Getopt::Long; +use POSIX 'strftime'; + +my $RCS_Id = '$Id$'; +my $this_program = 'help2man'; +my $this_version = '0.0'; + +if ($RCS_Id =~ /\$Id:\s+(\S+)\s+(\S+)/) +{ + $this_version = $2; + ($this_program = $1) =~ s/(\.pl)?,v$//; +} + +my $version_info = <<EOT; +$this_program $this_version + +Copyright (C) 1997, 98 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +EOT + +my $help_info = <<EOT; +`$this_program' generates a man page out of `--help' and `--version' output. + +Usage: $this_program [OPTION]... EXECUTABLE + + --name=STRING use `STRING' as the description for the NAME paragraph + --help print this help, then exit + --version print $this_program program version number, then exit + +EXECUTABLE should accept `--help' and `version' options. +EOT + +my ($name, $opt_help, $opt_version); + +# Parse options. +GetOptions ( + 'name=s' => \$name, + help => \$opt_help, + version => \$opt_version, +) or die $help_info; + +print $help_info and exit if $opt_help; +print $version_info and exit if $opt_version; + +die $help_info unless @ARGV == 1; + +# Turn off localisation of executable's ouput. +@ENV{qw(LANGUAGE LANG LC_ALL)} = qw(C C C); + +# Grab help and version paragraphs from executable +my @help = split /\n\n+/, `$ARGV[0] --help 2>/dev/null` + or die "$this_program: can't get `--help' info from $ARGV[0]\n"; + +my @version = split /\n\n+/, `$ARGV[0] --version 2>/dev/null` + or die "$this_program: can't get `--version' info from $ARGV[0]\n"; + +my $date = strftime "%B %Y", localtime; +my $program = $ARGV[0]; $program =~ s!.*/!!; +my $package = $program; +my $version; + +# The first line of the --version information is assumed to be in one +# of the following formats: +# +# <version> +# <program> <version> +# GNU <program> <version> +# <program> (GNU <package>) <version> +# <program> - GNU <package> <version> +# + +$_ = shift @version; + +if (/^(\S+)\s+\((GNU\s+[^)]+)\)\s+(.*)/ || + /^(\S+)\s+-\s*(GNU\s+\S+)\s+(.*)/) +{ + $program = $1; + $package = $2; + $version = $3; +} +elsif (/^(GNU\s+)?(\S+)\s+(.*)/) +{ + $program = $2; + $package = $1 ? "$1$2" : $2; + $version = $3; +} +else +{ + $version = $_; +} + +# Default description for NAME paragraph +$name ||= "short documentation for $program $version"; + +# Man pages traditionally have the page title in caps. +my $PROGRAM = uc $program; + +# Header. +print <<EOT; +.\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version. +.TH $PROGRAM 1 "$date" "$package $version" "GNU User's Manual" +.SH NAME +$program \\- $name +EOT + +my $accumulate = 1; +my @description = (); + +sub convert_option; + +# Output converted --help information. +for (@help) +{ + chomp; + + if (s/^Usage:\s+\S+\s+(.*)\n?//) + { + # Turn the usage clause into a synopsis. + print ".SH SYNOPSIS\n.B $program\n"; + + my $syn = $1; + $syn =~ s/(([][]|\.\.+)+)/\\fR$1\\fI/g; + s/^/\\fI/ unless $syn =~ s/^\\fR//; + + print "$syn\\fR\n"; + + # Dump any accumulated description text. + $accumulate = 0; + print ".SH DESCRITION\n"; + print @description; + + next unless $_; + } + + # Accumulate text if the synopsis has not been produced yet. + if ($accumulate) + { + push @description, ".PP\n" if @description; + push @description, "$_\n"; + next; + } + + # Catch bug report text. + if (/^Report bugs /) + { + print ".SH BUGS\n$_\n"; + next; + } + + # Special case for tar 1.12: --label=NAME\nPATTERN. + s{(\n[ \t]*)(-V,[ \t]+--label=NAME.*)\n[ \t]+PATTERN[ \t]+} + {$1$2$1\\&...=PATTERN }; + + # Convert options. + s/(\s)(-[][\w=-]+|\\&\S+)/$1.convert_option $2/ge; + + # Option subsections have second line indented. + print qq(.SS "$1"\n) if s/^(\S.*)\n(\s)/$2/; + + # Lines indented more than about 10 spaces may be assumed to be + # continuations of the previous line. + s/\n {10,}/ /g; + + # Indented paragraph. + if (/^\s/) + { + for (split /\n/) + { + s/^\s+//; + s/([^,])\s+/$1\n/; + print ".TP\n$_\n"; + } + } + # Anything else. + else + { + print ".PP\n$_\n"; + } +} + +# Refer to the real documentation. + +print <<EOT; +.SH SEE ALSO +The full documentation for +.B $program +is maintained as a Texinfo manual. If the +.B info +and +.B $program +programs are properly installed at your site, the command +.IP +.B info $program +.PP +should allow you to access the manual as an hypertext. +EOT + +# Output converted --version information. +for (@version) +{ + chomp; + + if (/^Copyright\s+\(C/) { print ".SH COPYRIGHT\n" } + elsif (/^Written\s+by/) { print ".SH AUTHOR\n" } + else { print ".PP\n"; } + + print "$_\n"; +} + +exit; + +# Convert option dashes to \- to stop nroff from hyphenating 'em, and +# embolden. Option arguments get italicised. +sub convert_option +{ + my $option = '\fB' . shift; + + $option =~ s/-/\\-/g; + unless ($option =~ s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/) + { + $option =~ s/=(.)/\\fR=\\fI$1/; + $option .= '\fR'; + } + + $option; +} diff --git a/doc/m4.1 b/doc/m4.1 new file mode 100644 index 00000000..beb6a584 --- /dev/null +++ b/doc/m4.1 @@ -0,0 +1,121 @@ +." DO NOT MODIFY THIS FILE! It was generated by helptoman 1.1.1.1. +.TH M4 1 "October 1998" "GNU m4 1.4h" "GNU User's Manual" +.SH NAME +m4 \- short documentation for m4 1.4h +.SH SYNOPSIS +.B m4 +[\fIOPTION\fR]...\fI \fR[\fIFILE\fR]...\fI\fR +.SH DESCRITION +.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\-\-interactive\fR +unbuffer output, ignore interrupts +.TP +\fB\-E\fR, \fB\-\-fatal\-warnings\fR +stop execution after first warning +.TP +\fB\-Q\fR, \fB\-\-quiet\fR, \fB\-\-silent\fR +suppress some warnings for builtins +.TP +\fB\-P\fR, \fB\-\-prefix\-builtins\fR +force a `m4_' prefix to all builtins +.SS "Preprocessor features:" +.TP +\fB\-I\fR, \fB\-\-include\fR=\fIDIRECTORY\fR +search this directory second for includes +.TP +\fB\-D\fR, \fB\-\-define=NAME\fR[=\fIVALUE\fR] +enter NAME has having VALUE, or empty +.TP +\fB\-U\fR, \fB\-\-undefine\fR=\fINAME\fR +delete builtin NAME +.TP +\fB\-s\fR, \fB\-\-synclines\fR +generate `#line NO "FILE"' lines +.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 +.TP +\fB\-L\fR, \fB\-\-nesting\-limit\fR=\fINUMBER\fR +change artificial nesting limit +.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=\fI[FLAGS]\fR +set debug level (no FLAGS implies `aeq') +.TP +\fB\-t\fR, \fB\-\-trace\fR=\fINAME\fR +trace NAME when it will be defined +.TP +\fB\-l\fR, \fB\-\-arglength\fR=\fINUM\fR +restrict macro tracing size +.TP +\fB\-o\fR, \fB\-\-error\-output\fR=\fIFILE\fR +redirect debug and trace output +.SS "FLAGS is any of:" +.TP +t +trace for all macro calls, not only traceon'ed +.TP +a +show actual arguments +.TP +e +show expansion +.TP +q +quote values as necessary, with a or e flag +.TP +c +show before collect, after collect and after call +.TP +x +add a unique macro call id, useful with c flag +.TP +f +say current input file name +.TP +l +say current input line number +.TP +p +show results of path searches +.TP +i +show changes in input files +.TP +V +shorthand for all of the above flags +.PP +If no FILE or if FILE is `-', standard input is read. +.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 allow you to access the manual as an hypertext. diff --git a/doc/m4.info b/doc/m4.info new file mode 100644 index 00000000..d3db9c3e --- /dev/null +++ b/doc/m4.info @@ -0,0 +1,112 @@ +This is Info file m4.info, produced by Makeinfo-1.55 from the input +file m4.texinfo. + +START-INFO-DIR-ENTRY +* m4: (m4). A powerful macro processor. +END-INFO-DIR-ENTRY + + This file documents the GNU `m4' utility. + + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 Free Software +Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +Indirect: +m4.info-1: 959 +m4.info-2: 50733 +m4.info-3: 97497 + +Tag Table: +(Indirect) +Node: Top959 +Node: Preliminaries6959 +Node: Intro7684 +Node: History9292 +Node: Invoking m410213 +Node: Bugs17007 +Node: Manual18275 +Node: Syntax19641 +Node: Names20228 +Node: Quoted strings20602 +Node: Other tokens21186 +Node: Comments21403 +Node: Macros22065 +Node: Invocation22558 +Node: Inhibiting Invocation23369 +Node: Macro Arguments26514 +Node: Quoting Arguments27778 +Node: Macro expansion28583 +Node: Definitions29246 +Node: Define30023 +Node: Arguments30834 +Node: Pseudo Arguments32315 +Node: Undefine34166 +Node: Defn34828 +Node: Pushdef35985 +Node: Indir37821 +Node: Builtin38583 +Node: Conditionals39027 +Node: Ifdef39734 +Node: Ifelse40503 +Node: Loops42269 +Node: Debugging45542 +Node: Dumpdef46121 +Node: Trace46969 +Node: Debug Levels48348 +Node: Debug Output50733 +Node: Input Control51253 +Node: Dnl51790 +Node: Changequote52916 +Node: Changecom54280 +Node: Changeword55564 +Node: M4wrap58767 +Node: File Inclusion59969 +Node: Include60285 +Node: Search Path62213 +Node: Diversions63000 +Node: Divert64237 +Node: Undivert65369 +Node: Divnum67304 +Node: Cleardiv67849 +Node: Text handling68885 +Node: Len69605 +Node: Index70003 +Node: Regexp70588 +Node: Substr71679 +Node: Translit72299 +Node: Patsubst73742 +Node: Format75833 +Node: Arithmetic77322 +Node: Incr77767 +Node: Eval78271 +Node: UNIX commands81270 +Node: Syscmd81741 +Node: Esyscmd82454 +Node: Sysval83400 +Node: Maketemp83807 +Node: Miscellaneous84864 +Node: Errprint85233 +Node: M4exit86224 +Node: Frozen files87010 +Node: Compatibility91906 +Node: Extensions92524 +Node: Incompatibilities94892 +Node: Other Incompat95334 +Node: Concept index97497 +Node: Macro index104371 + +End Tag Table diff --git a/doc/m4.info-1 b/doc/m4.info-1 new file mode 100644 index 00000000..d829eb0a --- /dev/null +++ b/doc/m4.info-1 @@ -0,0 +1,1495 @@ +This is Info file m4.info, produced by Makeinfo-1.55 from the input +file m4.texinfo. + +START-INFO-DIR-ENTRY +* m4: (m4). A powerful macro processor. +END-INFO-DIR-ENTRY + + This file documents the GNU `m4' utility. + + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 Free Software +Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: m4.info, Node: Top, Next: Preliminaries, Prev: (dir), Up: (dir) + +GNU `m4' +******** + + 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 Ren'e Seindal, with subsequent +changes by Franc,ois Pinard and other volunteers on the Internet. All +names and email addresses can be found in the file `THANKS' from the +GNU `m4' distribution. + + This is release 1.4. It is now to be considered stable, future +releases 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. So, it might go away, +do not count on it yet. + +* Menu: + +* Preliminaries:: Introduction and preliminaries +* Syntax:: Lexical and syntactic conventions + +* Macros:: How to invoke macros +* Definitions:: How to define new macros +* Conditionals:: Conditionals and loops + +* 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 +* UNIX commands:: Macros for running UNIX commands +* Miscellaneous:: Miscellaneous builtin macros +* Frozen files:: Fast loading of frozen states + +* Compatibility:: Compatibility with other versions of m4 +* Concept index:: Index for many concepts +* Macro index:: Index for all m4 macros + + -- The Detailed Node Listing -- + +Introduction and preliminaries + +* Intro:: Introduction to `m4' +* History:: Historical references + +* Invoking m4:: Invoking `m4' +* Bugs:: Problems and bugs +* Manual:: Using this manual + +Lexical and syntactic conventions + +* Names:: Macro names +* Quoted strings:: Quoting input to m4 +* Other tokens:: Other kinds of input tokens +* Comments:: Comments in m4 input + +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:: Pseudo 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 +* Loops:: Loops and recursion in m4 + +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 input 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 +* Cleardiv:: Discarding diverted text + +Macros for text handling + +* Len:: Calculating length of strings +* Index:: 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 + +Running UNIX commands + +* Syscmd:: Executing simple commands +* Esyscmd:: Reading the output of commands +* Sysval:: Exit codes +* Maketemp:: Making names for temporary files + +Miscellaneous builtin macros + +* Errprint:: Printing error messages +* M4exit:: Exiting from m4 + +Compatibility with other versions of `m4' + +* Extensions:: Extensions in GNU m4 +* Incompatibilities:: Facilities in System V m4 not in GNU m4 +* Other Incompat:: Other incompatibilities + + +File: m4.info, Node: Preliminaries, Next: Syntax, Prev: Top, Up: Top + +Introduction and preliminaries +****************************** + + This first chapter explains what is GNU `m4', 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 +* Invoking m4:: Invoking `m4' +* Bugs:: Problems and bugs +* Manual:: Using this manual + + +File: m4.info, Node: Intro, Next: History, Prev: Preliminaries, Up: Preliminaries + +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 UNIX commands, doing integer arithmetic, manipulating text in +various ways, recursion, etc... `m4' can be used either as a front-end +to a compiler, or as a macro processor in its own right. + + The `m4' macro processor is widely available on all UNIXes. +Usually, only a small percentage of users are aware of its existence. +However, those who do often become commited users. The growing +popularity of GNU Autoconf, which prerequires GNU `m4' for *generating* +the `configure' scripts, is an incentive for many to install it, while +these people will not themselves program in `m4'. GNU `m4' is mostly +compatible with the System V, Release 3 version, except for some minor +differences. *Note Compatibility:: for more details. + + Some people found `m4' to be fairly addictive. They first use `m4' +for simple problems, then take bigger and bigger challenges, learning +how to write complex `m4' sets of macros along the way. Once really +addicted, users pursue writing of sophisticated `m4' applications even +to solve simple problems, devoting more time debugging their `m4' +scripts than doing real work. Beware that `m4' may be dangerous for +the health of compulsive programmers. + + +File: m4.info, Node: History, Next: Invoking m4, Prev: Intro, Up: Preliminaries + +Historical references +===================== + + The historical notes included here are fairly incomplete, and not +authoritative at all. Please knowledgeable users help us to more +properly write this section. + + `GPM' has been an important ancestor of `m4'. See C. Stratchey: "A +General Purpose Macro generator", Computer Journal 8,3 (1965), pp. 225 +ff. `GPM' is also succintly described into David Gries classic +"Compiler Construction for Digital Computers". + + While `GPM' was *pure*, `m4' was meant to deal more with the true +intricacies of real life: macros could be recognized with being +pre-announced, skipping whitespace or end-of-lines was made easier, +more constructs were builtin instead of derived, etc. + + Originally, `m4' was the engine for Rational FORTRAN preprocessor, +that is, the `ratfor' equivalent of `cpp'. + + +File: m4.info, Node: Invoking m4, Next: Bugs, Prev: History, Up: Preliminaries + +Invoking `m4' +============= + + The format of the `m4' command is: + + `m4' [OPTION...] [MACRO-DEFINITIONS...] [INPUT-FILE...] + + All options begin with `-', or if long option names are used, with a +`--'. A long option name need not be written completely, and +unambigous prefix is sufficient. `m4' understands the following +options: + +`--version' + Print the version number of the program on standard output, then + immediately exit `m4' without reading any INPUT-FILES. + +`--help' + Print an help summary on standard output, then immediately exit + `m4' without reading any INPUT-FILES. + +`-G' +`--traditional' + Suppress all the extensions made in this implementation, compared + to the System V version. *Note Compatibility::, for a list of + these. + +`-E' +`--fatal-warnings' + Stop execution and exit `m4' once the first warning has been + issued, considering all of them to be fatal. + +`-dFLAGS' +`--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. + +`-lNUM' +`--arglength=NUM' + Restrict the size of the output generated by macro tracing. *Note + Debug Levels:: for more details. + +`-oFILE' +`--error-output=FILE' + Redirect debug and trace output to the named file. Error messages + are still printed on the standard error output. *Note Debug + Output:: for more details. + +`-IDIR' +`--include=DIR' + Make `m4' search DIR for included files that are not found in the + current working directory. *Note Search Path:: for more details. + +`-e' +`--interactive' + Makes this invocation of `m4' interactive. This means that all + output will be unbuffered, and interrupts will be ignored. + +`-s' +`--synclines' + Generate synchronisation lines, for use by the C preprocessor or + other similar tools. This 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 "FILENAME"', which are inserted as needed into the middle + of the input. Such directives mean that the following line + originated or was expanded from the contents of input file + FILENAME at line LINENUM. The `"FILENAME"' part is often omitted + when the file name did not change from the previous directive. + + Synchronisation directives are always given on complete lines per + themselves. When a synchronisation discrepancy occurs in the + middle of an output line, the associated synchronisation directive + is delayed until the beginning of the next generated line. + +`-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__'. + +`-WREGEXP' +`--word-regexp=REGEXP' + Use an alternative syntax for macro names. This experimental + option might not be present on all GNU `m4' implementations. + (*note Changeword::.). + +`-HN' +`--hashsize=N' + Make the internal hash table for symbol lookup be N entries big. + The number should be prime. The default is 509 entries. It + should not be necessary to increase this value, unless you define + an excessive number of macros. + +`-LN' +`--nesting-limit=N' + Artificially limit the nesting of macro calls to N levels, + stopping program execution if this limit is ever exceeded. When + not specified, nesting is limited to 250 levels. + + 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, while these do not necessarily consume much + memory or stack space. Through clever usage of rescanning loops, + one can request complex, time-consuming computations to `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! + +`-Q' +`--quiet' +`--silent' + Suppress warnings about missing or superflous arguments in macro + calls. + +`-B' +`-S' +`-T' + These options are present for compatibility with System V `m4', but + do nothing in this implementation. + +`-NN' +`--diversions=N' + 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. + + Macro definitions and deletions can be made on the command line, by +using the `-D' and `-U' options. They have the following format: + +`-DNAME' +`-DNAME=VALUE' +`--define=NAME' +`--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. + +`-UNAME' +`--undefine=NAME' + This deletes any predefined meaning NAME might have. Obviously, + only predefined macros can be deleted in this way. + +`-tNAME' +`--trace=NAME' + This enters NAME into the symbol table, as undefined but traced. + The macro will consequently be traced from the point it is defined. + +`-FFILE' +`--freeze-state FILE' + Once execution is finished, write out the frozen state on the + specified FILE (*note Frozen files::.). + +`-RFILE' +`--reload-state FILE' + Before execution starts, recover the internal state from the + specified frozen FILE (*note Frozen files::.). + + The remaining arguments on the command line are taken to be input +file names. If no names are present, the standard input is read. A +file name of `-' is taken to mean the standard input. + + The input files are read in the sequence given. The standard input +can only be read once, so the filename `-' should only appear once on +the command line. + + +File: m4.info, Node: Bugs, Next: Manual, Prev: Invoking m4, Up: Preliminaries + +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) +`bug-gnu-utils@prep.ai.mit.edu' or (UUCP) +`mit-eddie!prep.ai.mit.edu!bug-gnu-utils'. Please include the version +number of `m4' you are using. You can get this information with the +command `m4 --version'. + + 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 + +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 + + 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., + + regexp(STRING, REGEXP, opt REPLACEMENT) + + All macro arguments in `m4' are strings, but some are given special +interpretation, e.g., as numbers, filenames, regular expressions, etc. + + The `opt' before the third argument shows that this argument is +optional--if it is left out, it is taken to be the empty string. An +ellipsis (`...') last in the argument list indicates that any number of +arguments may follow. + + This document consistently writes and uses "builtin", without an +hyphen, as if it were an English word. This is how the `builtin' +primitive is spelled within `m4'. + + +File: m4.info, Node: Syntax, Next: Macros, Prev: Preliminaries, Up: Top + +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. + +* Menu: + +* Names:: Macro names +* Quoted strings:: Quoting input to m4 +* Other tokens:: Other kinds of input tokens +* Comments:: Comments in m4 input + + +File: m4.info, Node: Names, Next: Quoted strings, Prev: Syntax, Up: Syntax + +Names +===== + + A name is any sequence of letters, digits, and the character `_' +(underscore), where the first character is not a digit. If a name has +a macro definition, it will be subject to macro expansion (*note +Macros::.). + + Examples of legal names are: `foo', `_tmp', and `name01'. + + +File: m4.info, Node: Quoted strings, Next: Other tokens, Prev: Names, Up: Syntax + +Quoted strings +============== + + A quoted string is a sequence of characters surrounded by the quotes +``' and `'', where the number of start and end quotes within the string +balances. The value of a string token is the text, with one level of +quotes stripped off. Thus + + `' + + is the empty string, and + + ``quoted'' + + is the string + + `quoted' + + The quote characters can be changed at any time, using the builtin +macro `changequote'. *Note Changequote:: for more information. + + +File: m4.info, Node: Other tokens, Next: Comments, Prev: Quoted strings, Up: Syntax + +Other tokens +============ + + Any character, that is neither a part of a name, nor of a quoted +string, is a token by itself. + + +File: m4.info, Node: Comments, Prev: Other tokens, Up: Syntax + +Comments +======== + + 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 character can be +inhibited by quoting it. + + 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: Macros, Next: Definitions, Prev: Syntax, Up: Top + +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, Prev: Macros, Up: Macros + +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 + +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 when given arguments" refers to this specific +provision. + + There is also a command call option (`--prefix-builtins', or `-P') +which requires all builtin macro names to be prefixed by `m4_' for them +to be recognized. 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'. + + If your version of GNU `m4' has the `changeword' feature compiled +in, there 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 to be 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. It is also +possible to quote the empty string, but this works only *inside* the +name. For example: + + `divert' + `d'ivert + di`ver't + div`'ert + +all yield the string `divert'. While in both: + + `'divert + divert`' + +the `divert' builtin macro will be called. + + 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 + + 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 `dnl' macro to be recognized as such: + + define(`macro', `di$1') + macro(v)`'dnl + +Without the quotes, this would rather yield the string `divdnl' +followed by an end of line. + + 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' + +the input will produce the string `divert'. If the quote was removed, +the `divert' builtin would be called instead. + + +File: m4.info, Node: Macro Arguments, Next: Quoting Arguments, Prev: Inhibiting Invocation, Up: Macros + +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. If +there are too many arguments, the excess arguments are ignored. + + Normally `m4' will issue warnings if a builtin macro is called with +an inappropriate number of arguments, but it can be suppressed with the +`-Q' command line option. 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 leading unquoted whitespace is never part of an argument, +but trailing whitespace always is. + + +File: m4.info, Node: Quoting Arguments, Next: Macro expansion, Prev: Macro Arguments, Up: Macros + +Quoting macro arguments +======================= + + Each argument has leading unquoted 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 `() (() ('. + + 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 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. + + +File: m4.info, Node: Macro expansion, Prev: Quoting Arguments, Up: Macros + +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 + +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, which can be brought back at a later time. + +* Menu: + +* Define:: Defining a new macro +* Arguments:: Arguments to macros +* Pseudo Arguments:: Pseudo 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, Prev: Definitions, Up: Definitions + +Defining a macro +================ + + The normal way to define or redefine macros is to use the builtin +`define': + + define(NAME [, EXPANSION]) + +which defines NAME to expand to EXPANSION. If EXPANSION is not given, +it is taken to be empty. + + The expansion of `define' is void. + + 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 macro `define' is recognized only with parameters. + + +File: m4.info, Node: Arguments, Next: Pseudo Arguments, Prev: Define, Up: Definitions + +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. Here is a 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. + + 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 zero'th 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 + +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 + + 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.. + echo2(foo) + =>This is macro foo. + +*Note Trace::, if you do not understand this. + + 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', put a pair of +quotes after the `$'. This will prevent `m4' from interpreting the `$' +sign as a reference to an argument. + + +File: m4.info, Node: Undefine, Next: Defn, Prev: Pseudo Arguments, Up: Definitions + +Deleting a macro +================ + + A macro definition can be removed with `undefine': + + undefine(NAME) + +which removes the macro NAME. The macro name must necessarily be +quoted, since it will be expanded otherwise. + + The expansion of `undefine' is void. + + foo + =>foo + define(`foo', `expansion text') + => + foo + =>expansion text + undefine(`foo') + => + foo + =>foo + + It is not an error for NAME to have no macro definition. In that +case, `undefine' does nothing. + + The macro `undefine' is recognized only with parameters. + + +File: m4.info, Node: Defn, Next: Pushdef, Prev: Undefine, Up: Definitions + +Renaming macros +=============== + + It is possible to rename an already defined macro. To do this, you +need the builtin `defn': + + defn(NAME) + +which 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 ignored in any other context. + + 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 macro `defn' is recognized only with parameters. + + +File: m4.info, Node: Pushdef, Next: Indir, Prev: Defn, Up: Definitions + +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': + + pushdef(NAME [, EXPANSION]) + popdef(NAME) + +which are quite 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'. + + define(`foo', `Expansion one.') + => + foo + =>Expansion one. + pushdef(`foo', `Expansion two.') + => + foo + =>Expansion two. + popdef(`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 + + It is possible to temporarily redefine a builtin with `pushdef' and +`defn'. + + The macros `pushdef' and `popdef' are recognized only with +parameters. + + +File: m4.info, Node: Indir, Next: Builtin, Prev: Pushdef, Up: Definitions + +Indirect call of macros +======================= + + Any macro can be called indirectly with `indir': + + indir(NAME, ...) + +which results in a call to the macro NAME, which is passed the rest of +the arguments. This can be used to call macros with "illegal" 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'. + + +File: m4.info, Node: Builtin, Prev: Indir, Up: Definitions + +Indirect call of builtins +========================= + + Builtin macros can be called indirectly with `builtin': + + builtin(NAME, ...) + +which results in a call to the builtin NAME, which is passed the rest +of the arguments. This can be used, if NAME has been given another +definition that has covered the original. + + The macro `builtin' is recognized only with parameters. + + +File: m4.info, Node: Conditionals, Next: Debugging, Prev: Definitions, Up: Top + +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. E.g., 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 +* Loops:: Loops and recursion in m4 + + +File: m4.info, Node: Ifdef, Next: Ifelse, Prev: Conditionals, Up: Conditionals + +Testing macro definitions +========================= + + There are two different builtin conditionals in `m4'. The first is +`ifdef': + + ifdef(NAME, STRING-1, opt STRING-2) + +which makes it possible to test whether a macro is defined or not. 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). + + 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 + + The macro `ifdef' is recognized only with parameters. + + +File: m4.info, Node: Ifelse, Next: Loops, Prev: Ifdef, Up: Conditionals + +Comparing strings +================= + + 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: + + ifelse(COMMENT) + ifelse(STRING-1, STRING-2, EQUAL, opt NOT-EQUAL) + ifelse(STRING-1, STRING-2, EQUAL, ...) + +Used with only one argument, the `ifelse' simply discards it and +produces no output. This 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. + + 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. + + ifelse(foo, bar, `true') + => + ifelse(foo, foo, `true') + =>true + ifelse(foo, bar, `true', `false') + =>false + ifelse(foo, foo, `true', `false') + =>true + + 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, otherwise the procedure is repeated +with the first three arguments discarded. This calls for an example: + + ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') + =>seventh + + 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. + + The macro `ifelse' is recognized only with parameters. + + +File: m4.info, Node: Loops, Prev: Ifelse, Up: Conditionals + +Loops and recursion +=================== + + 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: + + shift(...) + +It takes any number of arguments, and expands to all but the first +argument, separated by commas, with each argument quoted. + + shift(bar) + => + shift(foo, bar, baz) + =>bar,baz + + An example of the use of `shift' is this macro, which reverses the +order of its arguments: + + 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. + + Here is an example of a loop macro that implements a simple forloop. +It can, for example, be used for simple counting: + + forloop(`i', 1, 8, `i ') + =>1 2 3 4 5 6 7 8 + + The arguments are a name for the iteration variable, the starting +value, the final value, and the text to be expanded for each iteration. +With this macro, the macro `i' is defined only within the loop. After +the loop, it retains whatever value it might have had before. + + For-loops can be nested, like + + 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 it is finished. If it has not finished, it increments the +iteration variable (using the predefined macro `incr', *note Incr::.), +and recurses. + + Here is the actual implementation of `forloop': + + define(`forloop', + `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') + define(`_forloop', + `$4`'ifelse($1, `$3', , + `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') + + Notice the careful use of quotes. Only three macro arguments are +unquoted, each for its own reason. Try to find out *why* these three +arguments are left unquoted, and see what happens if they are quoted. + + Now, even though these two macros are useful, they are still not +robust enough for general use. They lack even basic error handling of +cases like start value less than final value, and the first argument +not being a name. Correcting these errors are left as an exercise to +the reader. + + +File: m4.info, Node: Debugging, Next: Input Control, Prev: Conditionals, Up: Top + +How to debug macros and input +***************************** + + When writing macros for `m4', most of the time they woould not work +as intended (as is the case with most programming languages). There is +a little 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, Prev: Debugging, Up: Debugging + +Displaying macro definitions +============================ + + If you want to see what a name expands into, you can use the builtin +`dumpdef': + + dumpdef(...) + +which 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 directly on +the standard error output. + + The expansion of `dumpdef' is void. + + define(`foo', `Hello world.') + => + dumpdef(`foo') + error-->foo: `Hello world.' + => + dumpdef(`define') + error-->define: <define> + => + + The last example shows how builtin macros definitions are displayed. + + *Note Debug Levels:: for information on controlling the details of +the display. + + +File: m4.info, Node: Trace, Next: Debug Levels, Prev: Dumpdef, Up: Debugging + +Tracing macro calls +=================== + + It is possible to trace macro calls and expansions through the +builtins `traceon' and `traceoff': + + traceon(...) + traceoff(...) + +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 named macros are affected. + + 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 directly on the standard error 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. + + *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 + +Controlling debugging output +============================ + + The `-d' option to `m4' 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: + +`t' + Trace all macro calls made in this invocation of `m4'. + +`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'. + +`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'. + +`q' + Quote actual arguments and macro expansions in the display with the + current quotes. + +`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. + +`x' + Add a unique `macro call id' to each line of the trace output. + This is useful in connection with the `c' flag above. + +`f' + Show the name of the current input file in each trace output line. + +`l' + Show the the current input line number in each trace output line. + +`p' + Print a message when a named file is found through the path search + mecanism (*note Search Path::.), giving the actual filename used. + +`i' + Print a message each time the current input file is changed, + giving file name and input line number. + +`V' + A shorthand for all of the above flags. + + If no flags are specified with the `-d' option, the default is +`aeq'. The examples in the previous two sections assumed the default +flags. + + There is a builtin macro `debugmode', which allows on-the-fly +control of the debugging output format: + + debugmode(opt 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, the debugging flags are set to +zero (as if no `-d' was given), and with an empty argument the flags +are reset to the default. + diff --git a/doc/m4.info-2 b/doc/m4.info-2 new file mode 100644 index 00000000..aedf6a64 --- /dev/null +++ b/doc/m4.info-2 @@ -0,0 +1,1468 @@ +This is Info file m4.info, produced by Makeinfo-1.55 from the input +file m4.texinfo. + +START-INFO-DIR-ENTRY +* m4: (m4). A powerful macro processor. +END-INFO-DIR-ENTRY + + This file documents the GNU `m4' utility. + + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 Free Software +Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: m4.info, Node: Debug Output, Prev: Debug Levels, Up: Debugging + +Saving debugging output +======================= + + Debug and tracing output can be redirected to files using either the +`-o' option to `m4', or with the builtin macro `debugfile': + + debugfile(opt FILENAME) + +will send all further debug and trace output to FILENAME. If FILENAME +is empty, debug and trace output are discarded and if `debugfile' is +called without any arguments, debug and trace output are sent to the +standard error output. + + +File: m4.info, Node: Input Control, Next: File Inclusion, Prev: Debugging, Up: Top + +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 input until end of input + + +File: m4.info, Node: Dnl, Next: Changequote, Prev: Input Control, Up: Input Control + +Deleting whitespace in input +============================ + + The builtin `dnl' reads and discards all characters, up to and +including the first newline: + + dnl + +and it is often used in connection with `define', to remove the newline +that follow 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. + + +File: m4.info, Node: Changequote, Next: Changecom, Prev: Dnl, Up: Input Control + +Changing the quote characters +============================= + + The default quote delimiters can be changed with the builtin +`changequote': + + changequote(opt START, opt END) + +where START is the new start-quote delimiter and END is the new +end-quote delimiter. If any of the arguments are missing, the default +quotes (``' and `'') are used instead of the void arguments. + + The expansion of `changequote' is void. + + changequote([, ]) + => + define([foo], [Macro [foo].]) + => + foo + =>Macro foo. + + If no single character is appropriate, START and END can be of any +length. + + changequote([[, ]]) + => + define([[foo]], [[Macro [[[foo]]].]]) + => + foo + =>Macro [foo]. + + Changing the quotes to the empty strings will effectively disable the +quoting mechanism, leaving no way to quote text. + + define(`foo', `Macro `FOO'.') + => + changequote(, ) + => + foo + =>Macro `FOO'. + `foo' + =>`Macro `FOO'.' + + There is no way in `m4' to quote a string containing an unmatched +left quote, except using `changequote' to change the current quotes. + + Neither quote string should start with a letter or `_' (underscore), +as they will be confused with names in the input. Doing so disables +the quoting mechanism. + + +File: m4.info, Node: Changecom, Next: Changeword, Prev: Changequote, Up: Input Control + +Changing comment delimiters +=========================== + + The default comment delimiters can be changed with the builtin macro +`changecom': + + changecom(opt START, opt END) + +where START is the new start-comment delimiter and END is the new +end-comment delimiter. If any of the arguments are void, the default +comment delimiters (`#' and newline) are used instead of the void +arguments. 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 start comment delimiter. + + Calling `changecom' without any arguments disables the commenting +mechanism completely. + + define(`comment', `COMMENT') + => + changecom + => + # Not a comment anymore + =># Not a COMMENT anymore + + +File: m4.info, Node: Changeword, Next: M4wrap, Prev: Changecom, Up: Input Control + +Changing the lexical structure of words +======================================= + + The macro `changeword' and all associated functionnality is + experimental. It is only available if the `--enable-changeword' + option was given to `configure', at GNU `m4' installation time. + The functionnality might change or even go away in the future. + *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. Relaxing +`m4''s lexical rules might be useful (for example) if you wanted to +apply translations to a file of numbers: + + changeword(`[_a-zA-Z0-9]+') + define(1, 0) + =>1 + + 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: + + define(`_indir', defn(`indir')) + changeword(`_[_a-zA-Z0-9]*') + esyscmd(foo) + _indir(`esyscmd', `ls') + + 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'. + + `changeword' has another function. If the regular expression +supplied contains any bracketed subexpressions, then text outside the +first of these is discarded before symbol lookup. So: + + changecom(`/*', `*/') + changeword(`#\([_a-zA-Z0-9]*\)') + #esyscmd(ls) + + `m4' now requires a `#' mark at the beginning of every macro +invocation, so one can use `m4' to preprocess shell scripts without +getting `shift' commands swallowed, and plain text without losing +various common words. + + `m4''s macro substitution is based on text, while TeX's 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 + +Then, the `m4' version: + + define(a, `errprint(`Hello')') + changeword(`@\([_a-zA-Z0-9]*\)') + =>@a + + 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. + + +File: m4.info, Node: M4wrap, Prev: Changeword, Up: Input Control + +Saving 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': + + m4wrap(STRING, ...) + +which stores STRING and the rest of the arguments in a safe place, to +be reread when end of input is reached. + + define(`cleanup', `This is the `cleanup' actions. + ') + => + 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 actions. + + 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). + + +File: m4.info, Node: File Inclusion, Next: Diversions, Prev: Input Control, Up: Top + +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, Prev: File Inclusion, Up: File Inclusion + +Including named files +===================== + + There are two builtin macros in `m4' for including files: + + include(FILENAME) + sinclude(FILENAME) + +both of which cause the file named FILENAME 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 FILENAME. + + It is an error for an `include'd file not to exist. If you do not +want error messages about non-existent files, `sinclude' can be used to +include a file, if it exists, expanding to nothing if it does not. + + include(`no-such-file') + => + error-->30.include:2: m4: Cannot open no-such-file: No such file or directory + sinclude(`no-such-file') + => + + Assume in the following that the file `incl.m4' 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. + + The builtin macros `include' and `sinclude' are recognized only when +given arguments. + + +File: m4.info, Node: Search Path, Prev: Include, Up: File Inclusion + +Searching for include files +=========================== + + GNU `m4' allows included files to be found in other directories than +the current working directory. + + If a file is not found in the current working directory, and the file +name is not absolute, the file will be looked for in a specified search +path. First, the directories specified with the `-I' option will be +searched, in the order found on the command line. Second, 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 + +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. So, it is +theoretically possible that the number of diversions be limited by the +number of available file descriptors. + +* Menu: + +* Divert:: Diverting output +* Undivert:: Undiverting output +* Divnum:: Diversion numbers +* Cleardiv:: Discarding diverted text + + +File: m4.info, Node: Divert, Next: Undivert, Prev: Diversions, Up: Diversions + +Diverting output +================ + + Output is diverted using `divert': + + divert(opt NUMBER) + +where NUMBER is the diversion to be used. If NUMBER is left out, it is +assumed to be zero. + + 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. + + If output is diverted to a non-existent 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 how to avoid them. + + divert(-1) + define(`foo', `Macro `foo'.') + define(`bar', `Macro `bar'.') + divert + => + + This is a common programming idiom in `m4'. + + +File: m4.info, Node: Undivert, Next: Divnum, Prev: Divert, Up: Diversions + +Undiverting output +================== + + Diverted text can be undiverted explicitly using the builtin +`undivert': + + undivert(opt NUMBER, ...) + +which undiverts the diversions given by the arguments, in the order +given. If no arguments are supplied, all diversions are undiverted, in +numerical order. + + 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. + + 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. + + 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, assume the file `foo' +contains the word `bar': + + define(`bar', `BAR') + => + undivert(`foo') + =>bar + => + include(`foo') + =>BAR + => + + +File: m4.info, Node: Divnum, Next: Cleardiv, Prev: Undivert, Up: Diversions + +Diversion numbers +================= + + The builtin `divnum': + + divnum + +expands to the number of the current diversion. + + Initial divnum + =>Initial 0 + divert(1) + Diversion one: divnum + divert(2) + Diversion two: divnum + divert + => + ^D + => + =>Diversion one: 1 + => + =>Diversion two: 2 + + The last call of `divert' without argument is necessary, since the +undiverted text would otherwise be diverted itself. + + +File: m4.info, Node: Cleardiv, Prev: Divnum, Up: Diversions + +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: + + define(`cleardivert', + `pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') + => + + 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.) + + +File: m4.info, Node: Text handling, Next: Arithmetic, Prev: Diversions, Up: Top + +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:: 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, Prev: Text handling, Up: Text handling + +Calculating length of strings +============================= + + The length of a string can be calculated by `len': + + len(STRING) + +which expands to the length of STRING, as a decimal number. + + len() + =>0 + len(`abcdef') + =>6 + + The builtin macro `len' is recognized only when given arguments. + + +File: m4.info, Node: Index, Next: Regexp, Prev: Len, Up: Text handling + +Searching for substrings +======================== + + Searching for substrings is done with `index': + + index(STRING, SUBSTRING) + +which 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'. + + index(`gnus, gnats, and armadillos', `nat') + =>7 + index(`gnus, gnats, and armadillos', `dag') + =>-1 + + The builtin macro `index' is recognized only when given arguments. + + +File: m4.info, Node: Regexp, Next: Substr, Prev: Index, Up: Text handling + +Searching for regular expressions +================================= + + Searching for regular expressions is done with the builtin `regexp': + + regexp(STRING, REGEXP, opt REPLACEMENT) + +which 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. + + regexp(`GNUs not Unix', `\<[a-z]\w+') + =>5 + regexp(`GNUs not Unix', `\<Q\w*') + =>-1 + + If REPLACEMENT is supplied, `regexp' changes the expansion to this +argument, with `\N' substituted by the text matched by the Nth +parenthesized sub-expression of REGEXP, `\&' being the text the entire +regular expression matched. + + regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') + =>*** Unix *** nix *** + + The builtin macro `regexp' is recognized only when given arguments. + + +File: m4.info, Node: Substr, Next: Translit, Prev: Regexp, Up: Text handling + +Extracting substrings +===================== + + Substrings are extracted with `substr': + + substr(STRING, FROM, opt LENGTH) + +which 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. + + substr(`gnus, gnats, and armadillos', 6) + =>gnats, and armadillos + substr(`gnus, gnats, and armadillos', 6, 5) + =>gnats + + The builtin macro `substr' is recognized only when given arguments. + + +File: m4.info, Node: Translit, Next: Patsubst, Prev: Substr, Up: Text handling + +Translating characters +====================== + + Character translation is done with `translit': + + translit(STRING, CHARS, REPLACEMENT) + +which 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 are +deleted from the expansion. If REPLACEMENT is omitted, all characters +in STRING, that are present in CHARS are deleted from the expansion. + + 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. + + 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'. + + 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 + + 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. + + The builtin macro `translit' is recognized only when given arguments. + + +File: m4.info, Node: Patsubst, Next: Format, Prev: Translit, Up: Text handling + +Substituting text by regular expression +======================================= + + Global substitution in a string is done by `patsubst': + + patsubst(STRING, REGEXP, opt REPLACEMENT) + +which searches STRING for matches of REGEXP, and substitutes +REPLACEMENT for each match. The syntax for regular expressions is the +same as in GNU Emacs. + + 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 REGEXP, `\&' being the text the entire +regular expression matched. + + The REPLACEMENT argument can be omitted, in which case the text +matched by REGEXP is deleted. + + 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 + + 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. + + 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 + + The builtin macro `patsubst' is recognized only when given arguments. + + +File: m4.info, Node: Format, Prev: Patsubst, Up: Text handling + +Formatted output +================ + + Formatted output can be made with `format': + + format(FORMAT-STRING, ...) + +which works much like the C function `printf'. The first argument is a +format string, which can contain `%' specifications, and the expansion +of `format' is the formatted string. + + Its use is best described by a few examples: + + define(`foo', `The brown fox jumped over the lazy dog') + => + format(`The string "%s" is %d characters long', foo, len(foo)) + =>The string "The brown fox jumped over the lazy dog" is 38 characters long + + Using the `forloop' macro defined in *Note Loops::, this example +shows how `format' can be used to produce tabular output. + + 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 the normal `%' specifiers: `c', `s', `d', `o', `x', `X', +`u', `e', `E' and `f'; 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. + + +File: m4.info, Node: Arithmetic, Next: UNIX commands, Prev: Text handling, Up: Top + +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, Prev: Arithmetic, Up: Arithmetic + +Decrement and increment operators +================================= + + Increment and decrement of integers are supported using the builtins +`incr' and `decr': + + incr(NUMBER) + decr(NUMBER) + +which expand to the numerical value of NUMBER, incremented, or +decremented, respectively, by one. + + incr(4) + =>5 + decr(7) + =>6 + + The builtin macros `incr' and `decr' are recognized only when given +arguments. + + +File: m4.info, Node: Eval, Prev: Incr, Up: Arithmetic + +Evaluating integer expressions +============================== + + Integer expressions are evaluated with `eval': + + eval(EXPRESSION, opt RADIX, opt WIDTH) + +which expands to the value of EXPRESSION. + + Expressions can contain the following operators, listed in order of +decreasing precedence. + +`-' + Unary 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 many `m4' implementations use `^' as an alternate operator +for the exponentiation, while many others use `^' for the bitwise +exclusive-or. GNU `m4' changed its behavior: it used to exponentiate +for `^', it now computes the bitwise exclusive-or. + + Numbers without special prefix are given decimal. A simple `0' +prefix introduces an octal number. `0x' introduces an 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 any radix, 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 + define(`square', `eval(($1)**2)') + => + square(9) + =>81 + square(square(5)+1) + =>676 + define(`foo', `666') + => + eval(`foo'/6) + error-->51.eval:14: m4: Bad expression in eval: foo/6 + => + eval(foo/6) + =>111 + + As the second to last example shows, `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'. + + If RADIX is specified, it specifies the radix to be used in the +expansion. The default radix is 10. The result of `eval' is always +taken to be signed. The WIDTH argument specifies a minimum output +width. The result is zero-padded to extend the expansion to the +requested width. + + eval(666, 10) + =>666 + eval(666, 11) + =>556 + eval(666, 6) + =>3030 + eval(666, 6, 10) + =>0000003030 + eval(-666, 6, 10) + =>-000003030 + + Take note that RADIX cannot be larger than 36. + + The builtin macro `eval' is recognized only when given arguments. + + +File: m4.info, Node: UNIX commands, Next: Miscellaneous, Prev: Arithmetic, Up: Top + +Running UNIX commands +********************* + + There are a few builtin macros in `m4' that allow you to run UNIX +commands from within `m4'. + +* Menu: + +* Syscmd:: Executing simple commands +* Esyscmd:: Reading the output of commands +* Sysval:: Exit codes +* Maketemp:: Making names for temporary files + + +File: m4.info, Node: Syscmd, Next: Esyscmd, Prev: UNIX commands, Up: UNIX commands + +Executing simple commands +========================= + + Any shell command can be executed, using `syscmd': + + syscmd(SHELL-COMMAND) + +which 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 output buffers. +The default standard input, output and error of SHELL-COMMAND are the +same as those of `m4'. + + The builtin macro `syscmd' is recognized only when given arguments. + + +File: m4.info, Node: Esyscmd, Next: Sysval, Prev: Syscmd, Up: UNIX commands + +Reading the output of commands +============================== + + If you want `m4' to read the output of a UNIX command, use `esyscmd': + + esyscmd(SHELL-COMMAND) + +which expands to the standard output of the shell command SHELL-COMMAND. + + Prior to executing the command, `m4' flushes its output buffers. +The default standard input and error output 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'. + + Assume you are positioned into the `checks' directory of GNU `m4' +distribution, then: + + define(`vice', `esyscmd(grep Vice ../COPYING)') + => + vice + => Ty Coon, President of Vice + => + + Note how the expansion of `esyscmd' has a trailing newline. + + The builtin macro `esyscmd' is recognized only when given arguments. + + +File: m4.info, Node: Sysval, Next: Maketemp, Prev: Esyscmd, Up: UNIX commands + +Exit codes +========== + + To see whether a shell command succeeded, use `sysval': + + sysval + +which expands to the exit status of the last shell command run with +`syscmd' or `esyscmd'. + + syscmd(`false') + => + ifelse(sysval, 0, zero, non-zero) + =>non-zero + syscmd(`true') + => + sysval + =>0 + + +File: m4.info, Node: Maketemp, Prev: Sysval, Up: UNIX commands + +Making names for 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, +`maketemp', for making temporary file names: + + maketemp(TEMPLATE) + +which expands to a name of a non-existent file, made from the string +TEMPLATE, which should end with the string `XXXXXX'. The six `X''s are +then replaced, usually with something that includes the process id of +the `m4' process, in order to make the filename unique. + + maketemp(`/tmp/fooXXXXXX') + =>/tmp/fooa07346 + maketemp(`/tmp/fooXXXXXX') + =>/tmp/fooa07346 + + As seen in the example, several calls of `maketemp' might expand to +the same string, since the selection criteria is whether the file exists +or not. If a file has not been created before the next call, the two +macro calls might expand to the same name. + + The builtin macro `maketemp' is recognized only when given arguments. + + +File: m4.info, Node: Miscellaneous, Next: Frozen files, Prev: UNIX commands, Up: Top + +Miscellaneous builtin macros +**************************** + + This chapter describes various builtins, that do not really belong in +any of the previous chapters. + +* Menu: + +* Errprint:: Printing error messages +* M4exit:: Exiting from m4 + + +File: m4.info, Node: Errprint, Next: M4exit, Prev: Miscellaneous, Up: Miscellaneous + +Printing error messages +======================= + + You can print error messages using `errprint': + + errprint(MESSAGE, ...) + +which simply prints MESSAGE and the rest of the arguments on the +standard error output. + + The expansion of `errprint' is void. + + errprint(`Illegal arguments to forloop + ') + error-->Illegal arguments to forloop + => + + A trailing newline is *not* printed automatically, so it must be +supplied as part of the argument, as in the example. (BSD flavored +`m4''s do append a trailing newline on each `errprint' call). + + To make it possible to specify the location of the error, two +utility builtins exist: + + __file__ + __line__ + +which expands to the quoted name of the current input file, and the +current input line number in that file. + + errprint(`m4:'__file__:__line__: `Input error + ') + error-->m4:56.errprint:2: Input error + => + + +File: m4.info, Node: M4exit, Prev: Errprint, Up: Miscellaneous + +Exiting from `m4' +================= + + If you need to exit from `m4' before the entire input has been read, +you can use `m4exit': + + m4exit(opt CODE) + +which causes `m4' to exit, with exit code CODE. If CODE is left out, +the exit code is zero. + + define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* + ')m4exit(1)') + => + fatal_error(`This is a BAD one, buster') + error-->m4: 57.m4exit: 5: fatal error: This is a BAD one, buster + + After this macro call, `m4' will exit with exit code 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. + + +File: m4.info, Node: Frozen files, Next: Compatibility, Prev: Miscellaneous, Up: Top + +Fast loading of frozen states +***************************** + + 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, `include''d from this input file. + + 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. Presume the user +repeatedly uses: + + m4 base.m4 input.m4 + +with a varying contents of `input.m4', but a rather fixed contents for +`base.m4'. Then, the user might rather execute: + + m4 -F base.m4f base.m4 + +once, and further execute, as often as needed: + + m4 -R base.m4f input.m4 + +with the varying input. The first call, containing the `-F' option, +only reads and executes file `base.m4', so defining various application +macros and computing other initializations. Only 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''s memory, from `base.m4f', *prior* to reading +any other input files. By this mean, 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'. Also, +interactions for some options of `m4' being used in one call and not +for the next, have not been fully analyzed yet. On the other end, you +may be confident that stacks of `pushdef''ed definitions are handled +correctly, so are `undefine''d or renamed builtins, changed strings for +quotes or comments. + + 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::.). + + Frozen files are sharable across architectures. It is safe to write +a frozen file one one machine and read it on another, given that the +second machine uses the same, or a newer version of GNU `m4'. These +are simple (editable) text files, made up of directives, each starting +with a capital letter and ending with a newline (NL). Wherever a +directive is expected, the character `#' introduces a comment line, +empty lines are also ignored. In the following descriptions, LENGTHs +always refer to corresponding STRINGs. Numbers are always expressed in +decimal. The directives are: + +`V NUMBER NL' + Confirms the format of the file. NUMBER should be 1. + +`C LENGTH1 , LENGTH2 NL STRING1 STRING2 NL' + Uses STRING1 and STRING2 as the beginning comment and end comment + strings. + +`Q LENGTH1 , LENGTH2 NL STRING1 STRING2 NL' + Uses STRING1 and STRING2 as the beginning quote and end quote + strings. + +`F LENGTH1 , LENGTH2 NL STRING1 STRING2 NL' + Defines, through `pushdef', a definition for STRING1 expanding to + the function whose builtin name is STRING2. + +`T LENGTH1 , LENGTH2 NL STRING1 STRING2 NL' + Defines, though `pushdef', a definition for STRING1 expanding to + the text given by STRING2. + +`D NUMBER, LENGTH NL STRING NL' + Selects diversion NUMBER, making it current, then copy STRING 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 STRING. With 0 as the diversion + NUMBER, STRING will be issued on standard output at reload time, + however this may not be produced from within `m4'. + + +File: m4.info, Node: Compatibility, Next: Concept index, Prev: Frozen files, Up: Top + +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 Incompat:: Other incompatibilities + + +File: m4.info, Node: Extensions, Next: Incompatibilities, Prev: Compatibility, Up: Compatibility + +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, 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::.). + + * 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 current input file and the current input line + number are accessible through the builtins `__file__' and + `__line__' (*note Errprint::.). + + * 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::.). + + In addition to the above extensions, GNU `m4' implements the +following command line options: `-F', `-G', `-I', `-L', `-R', `-V', +`-W', `-d', `-l', `-o' 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 Incompat, Prev: Extensions, Up: Compatibility + +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. + + * System V `m4' supports multiple arguments to `defn'. This is not + implemented in GNU `m4'. Its usefulness is unclear to me. + + +File: m4.info, Node: Other Incompat, Prev: Incompatibilities, Up: Compatibility + +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 filenames 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. + + I expect the sync line option to be 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 prohiting autoreferential 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 leave 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. + + * GNU `m4' without `-G' option will define the macro `__gnu__' to + expand to the empty string. + + On UNIX systems, GNU `m4' without the `-G' option will define the + macro `__unix__', otherwise the macro `unix'. Both will expand to + the empty string. + diff --git a/doc/m4.info-3 b/doc/m4.info-3 new file mode 100644 index 00000000..c21385ea --- /dev/null +++ b/doc/m4.info-3 @@ -0,0 +1,227 @@ +This is Info file m4.info, produced by Makeinfo-1.55 from the input +file m4.texinfo. + +START-INFO-DIR-ENTRY +* m4: (m4). A powerful macro processor. +END-INFO-DIR-ENTRY + + This file documents the GNU `m4' utility. + + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 Free Software +Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: m4.info, Node: Concept index, Next: Macro index, Prev: Compatibility, Up: Top + +Concept index +************* + +* Menu: + +* Arguments to macros: Arguments. +* arguments to macros: Macro Arguments. +* arguments to macros, special: Pseudo Arguments. +* arguments, quoted macro: Quoting Arguments. +* arithmetic: Arithmetic. +* builtins, indirect call of: Builtin. +* call of builtins, indirect: Builtin. +* call of macros, indirect: Indir. +* changing comment delimiters: Changecom. +* changing the quote delimiters: Changequote. +* characters, translating: Translit. +* command line, filenames on the: Invoking m4. +* command line, macro definitions on the: Invoking m4. +* command line, options: Invoking m4. +* commands, exit code from UNIX: Sysval. +* commands, running UNIX: UNIX commands. +* comment delimiters, changing: Changecom. +* comments: Comments. +* comments, copied to output: Changecom. +* comparing strings: Ifelse. +* compatibility: Compatibility. +* conditionals: Ifdef. +* controlling debugging output: Debug Levels. +* counting loops: Loops. +* debugging output, controlling: Debug Levels. +* debugging output, saving: Debug Output. +* decrement operator: Incr. +* defining new macros: Definitions. +* definitions, displaying macro: Dumpdef. +* deleting macros: Undefine. +* deleting whitespace in input: Dnl. +* discarding diverted text: Cleardiv. +* displaying macro definitions: Dumpdef. +* diversion numbers: Divnum. +* diverted text, discarding: Cleardiv. +* diverting output to files: Divert. +* dumping into frozen file: Frozen files. +* error messages, printing: Errprint. +* evaluation, of integer expressions: Eval. +* executing UNIX commands: UNIX commands. +* exit code from UNIX commands: Sysval. +* exiting from m4: M4exit. +* expansion of macros: Macro expansion. +* expansion, tracing macro: Trace. +* expressions, evaluation of integer: Eval. +* extracting substrings: Substr. +* fast loading of frozen files: Frozen files. +* file inclusion: Undivert. +* file inclusion: File Inclusion. +* filenames, on the command line: Invoking m4. +* files, diverting output to: Divert. +* files, names of temporary: Maketemp. +* forloops: Loops. +* formatted output: Format. +* frozen files for fast loading: Frozen files. +* GNU extensions: Extensions. +* GNU extensions: Frozen files. +* GNU extensions: Esyscmd. +* GNU extensions: Format. +* GNU extensions: Patsubst. +* GNU extensions: Regexp. +* GNU extensions: Undivert. +* GNU extensions: Search Path. +* GNU extensions: Debug Output. +* GNU extensions: Debug Levels. +* GNU extensions: Builtin. +* GNU extensions: Indir. +* GNU extensions: Arguments. +* included files, search path for: Search Path. +* inclusion, of files: Undivert. +* inclusion, of files: File Inclusion. +* increment operator: Incr. +* indirect call of builtins: Builtin. +* indirect call of macros: Indir. +* initialization, frozen states: Frozen files. +* input tokens: Syntax. +* input, saving: M4wrap. +* integer arithmetic: Arithmetic. +* integer expression evaluation: Eval. +* length of strings: Len. +* lexical structure of words: Changeword. +* loops: Loops. +* loops, counting: Loops. +* macro definitions, on the command line: Invoking m4. +* macro expansion, tracing: Trace. +* macro invocation: Invocation. +* macros, arguments to: Arguments. +* macros, arguments to: Macro Arguments. +* macros, displaying definitions: Dumpdef. +* macros, expansion of: Macro expansion. +* macros, how to define new: Definitions. +* macros, how to delete: Undefine. +* macros, how to rename: Defn. +* macros, indirect call of: Indir. +* macros, quoted arguments to: Quoting Arguments. +* macros, recursive: Loops. +* macros, special arguments to: Pseudo Arguments. +* macros, temporary redefinition of: Pushdef. +* messages, printing error: Errprint. +* multibranches: Ifelse. +* names: Names. +* options, command line: Invoking m4. +* output, diverting to files: Divert. +* output, formatted: Format. +* output, saving debugging: Debug Output. +* pattern substitution: Patsubst. +* printing error messages: Errprint. +* quote delimiters, changing the: Changequote. +* quoted macro arguments: Quoting Arguments. +* quoted string: Quoted strings. +* recursive macros: Loops. +* redefinition of macros, temporary: Pushdef. +* regular expressions: Patsubst. +* regular expressions: Regexp. +* reloading a frozen file: Frozen files. +* renaming macros: Defn. +* running UNIX commands: UNIX commands. +* saving debugging output: Debug Output. +* saving input: M4wrap. +* search path for included files: Search Path. +* special arguments to macros: Pseudo Arguments. +* strings, length of: Len. +* substitution by regular expression: Patsubst. +* substrings, extracting: Substr. +* temporary filenames: Maketemp. +* temporary redefinition of macros: Pushdef. +* tokens: Syntax. +* tracing macro expansion: Trace. +* translating characters: Translit. +* undefining macros: Undefine. +* UNIX commands, exit code from: Sysval. +* UNIX commands, running: UNIX commands. +* words, lexical structure of: Changeword. + + +File: m4.info, Node: Macro index, Prev: Concept index, Up: Top + +Macro index +*********** + + References are exclusively to the places where a builtin is +introduced the first time. Names starting and ending with `__' have +these characters removed in the index. + +* Menu: + +* builtin: Builtin. +* changecom: Changecom. +* changequote: Changequote. +* changeword: Changeword. +* debugfile: Debug Output. +* debugmode: Debug Levels. +* decr: Incr. +* define: Define. +* defn: Defn. +* divert: Divert. +* divnum: Divnum. +* dnl: Dnl. +* dumpdef: Dumpdef. +* errprint: Errprint. +* esyscmd: Esyscmd. +* eval: Eval. +* file: Errprint. +* format: Format. +* gnu: Other Incompat. +* ifdef: Ifdef. +* ifelse: Ifelse. +* include: Include. +* incr: Incr. +* index: Index. +* indir: Indir. +* len: Len. +* line: Errprint. +* m4exit: M4exit. +* m4wrap: M4wrap. +* maketemp: Maketemp. +* patsubst: Patsubst. +* popdef: Pushdef. +* pushdef: Pushdef. +* regexp: Regexp. +* shift: Loops. +* sinclude: Include. +* substr: Substr. +* syscmd: Syscmd. +* sysval: Sysval. +* traceoff: Trace. +* traceon: Trace. +* translit: Translit. +* undefine: Undefine. +* undivert: Undivert. +* unix: Other Incompat. + + diff --git a/doc/m4.texinfo b/doc/m4.texinfo new file mode 100644 index 00000000..5d3f36bf --- /dev/null +++ b/doc/m4.texinfo @@ -0,0 +1,3415 @@ +\input texinfo +@c %**start of header +@setfilename m4.info +@settitle GNU macro processor +@finalout +@c %**end of header + +@include version.texi + +@ifinfo +@set Francois Franc,ois +@end ifinfo +@tex +@set Francois Fran\noexpand\ptexc cois +@end tex + +@ifinfo +@format +START-INFO-DIR-ENTRY +* m4: (m4). A powerful macro processor. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +This file documents the GNU @code{m4} utility. + +Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end ifinfo + +@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 +Copyright @copyright{} 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end titlepage + +@ifinfo +@node Top, Preliminaries, (dir), (dir) +@top GNU @code{m4} + +@c @item @b{@code{m4}} @value{hfillkludge} (UtilD, UtilT, SrcCD) +@c +GNU @code{m4} is an implementation of the traditional UNIX macro +processor. It is mostly SVR4 compatible, although it has some +extensions (for example, handling more than 9 positional parameters +to macros). @code{m4} also has builtin functions for including +files, running shell commands, doing arithmetic, etc. Autoconf needs +GNU @code{m4} for generating @file{configure} scripts, but not for +running them. + +GNU @code{m4} was originally written by Ren@'e Seindal, with +subsequent changes by @value{Francois} Pinard and other volunteers +on the Internet. All names and email addresses can be found in the +file @file{THANKS} from the GNU @code{m4} distribution. + +This is release @value{VERSION}. It is now to be considered stable, +future releases 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. So, it +might go away, do not count on it yet. + +@menu +* Preliminaries:: Introduction and preliminaries +* Syntax:: Lexical and syntactic conventions + +* Macros:: How to invoke macros +* Definitions:: How to define new macros +* Conditionals:: Conditionals and loops + +* 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 +* UNIX commands:: Macros for running UNIX commands +* Miscellaneous:: Miscellaneous builtin macros +* Frozen files:: Fast loading of frozen states + +* Compatibility:: Compatibility with other versions of m4 +* Concept index:: Index for many concepts +* Macro index:: Index for all m4 macros + + --- The Detailed Node Listing --- + +Introduction and preliminaries + +* Intro:: Introduction to @code{m4} +* History:: Historical references + +* Invoking m4:: Invoking @code{m4} +* Bugs:: Problems and bugs +* Manual:: Using this manual + +Lexical and syntactic conventions + +* Names:: Macro names +* Quoted strings:: Quoting input to m4 +* Other tokens:: Other kinds of input tokens +* Comments:: Comments in m4 input + +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:: Pseudo 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 +* Loops:: Loops and recursion in m4 + +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 input 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 +* Cleardiv:: Discarding diverted text + +Macros for text handling + +* Len:: Calculating length of strings +* Index:: 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 + +Running UNIX commands + +* Syscmd:: Executing simple commands +* Esyscmd:: Reading the output of commands +* Sysval:: Exit codes +* Maketemp:: Making names for temporary files + +Miscellaneous builtin macros + +* Errprint:: Printing error messages +* M4exit:: Exiting from m4 + +Compatibility with other versions of @code{m4} + +* Extensions:: Extensions in GNU m4 +* Incompatibilities:: Facilities in System V m4 not in GNU m4 +* Other Incompat:: Other incompatibilities +@end menu + +@end ifinfo + +@node Preliminaries, Syntax, Top, Top +@chapter Introduction and preliminaries + +This first chapter explains what is GNU @code{m4}, 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 +* Invoking m4:: Invoking @code{m4} +* Bugs:: Problems and bugs +* Manual:: Using this manual +@end menu + +@node Intro, History, Preliminaries, Preliminaries +@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 UNIX commands, doing integer +arithmetic, manipulating text in various ways, 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. +Usually, only a small percentage of users are aware of its existence. +However, those who do often become commited users. The growing +popularity of GNU Autoconf, which prerequires GNU @code{m4} for +@emph{generating} the @file{configure} scripts, is an incentive +for many to install it, while these people will not themselves +program in @code{m4}. GNU @code{m4} is mostly compatible with the +System V, Release 3 version, except for some minor differences. +@xref{Compatibility} for more details. + +Some people found @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 @code{m4} sets of 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, Invoking m4, Intro, Preliminaries +@section Historical references + +The historical notes included here are fairly incomplete, and not +authoritative at all. Please knowledgeable users help us to more +properly write this section. + +@code{GPM} has been 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 succintly described into +David Gries classic ``Compiler Construction for Digital Computers''. + +While @code{GPM} was @emph{pure}, @code{m4} was meant to deal more +with the true intricacies of real life: macros could be recognized +with being pre-announced, skipping whitespace or end-of-lines was +made easier, more constructs were builtin instead of derived, etc. + +Originally, @code{m4} was the engine for Rational FORTRAN preprocessor, +that is, the @code{ratfor} equivalent of @code{cpp}. + +@node Invoking m4, Bugs, History, Preliminaries +@section Invoking @code{m4} + +The format of the @code{m4} command is: + +@comment ignore +@example +@code{m4} [@var{option}@dots{}] [@var{macro-definitions}@dots{}] [@var{input-file}@dots{}] +@end example + +@cindex command line, options +@cindex options, command line +All options begin with @samp{-}, or if long option names are used, with +a @samp{--}. A long option name need not be written completely, and +unambigous prefix is sufficient. @code{m4} understands the following +options: + +@table @code +@item --version +Print the version number of the program on standard output, then +immediately exit @code{m4} without reading any @var{input-files}. + +@item --help +Print an help summary on standard output, then immediately exit +@code{m4} without reading any @var{input-files}. + +@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 -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 -d@var{flags} +@itemx --debug=@var{flags} +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}. + +@item -l@var{num} +@itemx --arglength=@var{num} +Restrict the size of the output generated by macro tracing. @xref{Debug +Levels} for more details. + +@item -o@var{file} +@itemx --error-output=@var{file} +Redirect debug and trace output to the named file. Error messages are +still printed on the standard error output. @xref{Debug Output} for +more details. + +@item -I@var{dir} +@itemx --include=@var{dir} +Make @code{m4} search @var{dir} for included files that are not found in +the current working directory. @xref{Search Path} for more details. + +@item -e +@itemx --interactive +Makes this invocation of @code{m4} interactive. This means that all +output will be unbuffered, and interrupts will be ignored. + +@item -s +@itemx --synclines +Generate synchronisation lines, for use by the C preprocessor or other +similar tools. This 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{filename}"}, which are inserted as needed into the middle of the +input. Such directives mean that the following line originated or was +expanded from the contents of input file @var{filename} at line +@var{linenum}. The @samp{"@var{filename}"} part is often omitted when +the file name did not change from the previous directive. + +Synchronisation directives are always given on complete lines per +themselves. When a synchronisation discrepancy occurs in the middle of +an output line, the associated synchronisation directive is delayed +until the beginning of the next generated line. + +@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__}. + +@item -W@var{REGEXP} +@itemx --word-regexp=@var{REGEXP} +Use an alternative syntax for macro names. This experimental +option might not be present on all GNU @code{m4} implementations. +(@pxref{Changeword}). + +@item -H@var{n} +@itemx --hashsize=@var{n} +Make the internal hash table for symbol lookup be @var{n} entries big. +The number should be prime. 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{n} +@itemx --nesting-limit=@var{n} +Artificially limit the nesting of macro calls to @var{n} levels, +stopping program execution if this limit is ever exceeded. When not +specified, nesting is limited to 250 levels. + +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, while these do not necessarily consume much memory +or stack space. Through clever usage of rescanning loops, one can +request complex, time-consuming computations to @code{m4} with useful +results. Putting limitations in this area would break @code{m4} power. +There are many pathological cases: @w{@samp{define(`a', `a')a}} is +only the simplest example (but @pxref{Compatibility}). Expecting GNU +@code{m4} to detect these would be a little like expecting a compiler +system to detect and diagnose endless loops: it is a quite @emph{hard} +problem in general, if not undecidable! + +@item -Q +@itemx --quiet +@itemx --silent +Suppress warnings about missing or superflous arguments in macro calls. + +@item -B +@itemx -S +@itemx -T +These options are present for compatibility with System V @code{m4}, but +do nothing in this implementation. + +@item -N@var{n} +@itemx --diversions=@var{n} +These options are present only for compatibility with previous +versions of 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. + +@end table + +@cindex macro definitions, on the command line +@cindex command line, macro definitions on the +Macro definitions and deletions can be made on the command line, by +using the @samp{-D} and @samp{-U} options. They have the following +format: + +@table @code +@item -D@var{name} +@itemx -D@var{name}=@var{value} +@itemx --define=@var{name} +@itemx --define=@var{name}=@var{value} +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. + +@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. + +@item -t@var{name} +@itemx --trace=@var{name} +This enters @var{name} into the symbol table, as undefined but traced. +The macro will consequently be traced from the point it is defined. + +@item -F@var{file} +@itemx --freeze-state @var{file} +Once execution is finished, write out the frozen state on the specified +@var{file} (@pxref{Frozen files}). + +@item -R@var{file} +@itemx --reload-state @var{file} +Before execution starts, recover the internal state from the specified +frozen @var{file} (@pxref{Frozen files}). + +@end table + +@cindex command line, filenames on the +@cindex filenames, on the command line +The remaining arguments on the command line are taken to be input file +names. If no names are present, the standard input is read. A file +name of @file{-} is taken to mean the standard input. + +The input files are read in the sequence given. The standard input can +only be read once, so the filename @file{-} should only appear once on +the command line. + +@node Bugs, Manual, Invoking m4, Preliminaries +@section Problems and bugs + +If you have problems with GNU @code{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) +@file{bug-gnu-utils@@prep.ai.mit.edu} or (UUCP) +@file{mit-eddie!prep.ai.mit.edu!bug-gnu-utils}. Please include the +version number of @code{m4} you are using. You can get this information +with the command @samp{m4 --version}. + +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, , Bugs, Preliminaries +@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 + +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., + +@comment ignore +@example +regexp(@var{string}, @var{regexp}, opt @var{replacement}) +@end example + +All macro arguments in @code{m4} are strings, but some are given special +interpretation, e.g., as numbers, filenames, regular expressions, etc. + +The @samp{opt} before the third argument shows that this argument is +optional---if it is left out, it is taken to be the empty string. An +ellipsis (@samp{...}) last in the argument list indicates that any +number of arguments may follow. + +This document consistently writes and uses @dfn{builtin}, without an +hyphen, as if it were an English word. This is how the @code{builtin} +primitive is spelled within @code{m4}. + +@node Syntax, Macros, Preliminaries, Top +@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. + +@menu +* Names:: Macro names +* Quoted strings:: Quoting input to m4 +* Other tokens:: Other kinds of input tokens +* Comments:: Comments in m4 input +@end menu + +@node Names, Quoted strings, Syntax, Syntax +@section Names + +@cindex names +A name is any sequence of letters, digits, and the character @kbd{_} +(underscore), where the first character is not a digit. If a +name has a macro definition, it will be subject to macro expansion +(@pxref{Macros}). + +Examples of legal names are: @samp{foo}, @samp{_tmp}, and @samp{name01}. + +@node Quoted strings, Other tokens, Names, Syntax +@section Quoted strings + +@cindex quoted string +A quoted string is a sequence of characters surrounded by the quotes +@kbd{`} and @kbd{'}, where the number of start and end quotes within the +string balances. The value of a string token is the text, with one +level of quotes stripped off. Thus + +@comment ignore +@example +`' +@end example + +is the empty string, and + +@comment ignore +@example +`@w{}`quoted'@w{}' +@end example + +is the string + +@comment ignore +@example +`quoted' +@end example + +The quote characters can be changed at any time, using the builtin macro +@code{changequote}. @xref{Changequote} for more information. + +@node Other tokens, Comments, Quoted strings, Syntax +@section Other tokens + +Any character, that is neither a part of a name, nor of a quoted string, +is a token by itself. + +@node Comments, , Other tokens, Syntax +@section Comments + +@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 character +can be inhibited by quoting it. + +The comment delimiters can be changed to any string at any time, using +the builtin macro @code{changecom}. @xref{Changecom} for more +information. + +@c FIXME: more examples would be useful here --ADR + +@node Macros, Definitions, Syntax, Top +@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, Inhibiting Invocation, Macros, Macros +@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, ..., 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, Macro Arguments, Invocation, Macros +@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, 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 when given arguments'' refers to this +specific provision. + +There is also a command call option (@code{--prefix-builtins}, or +@code{-P}) which requires all builtin macro names to be prefixed +by @samp{m4_} for them to be recognized. 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}. + +If your version of GNU @code{m4} has the @code{changeword} feature +compiled in, there 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 to be 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. It is also possible +to quote the empty string, but this works only @emph{inside} the name. +For example: + +@comment ignore +@example +`divert' +`d'ivert +di`ver't +div`'ert +@end example + +@noindent +all yield the string @samp{divert}. While in both: + +@comment ignore +@example +`'divert +divert`' +@end example + +@noindent +the @code{divert} builtin macro will be called. + +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: + +@comment ignore +@example +define(`x', `substr(ab') +define(`y', `cde, 3, 2)') +x`'y +@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 @code{dnl} macro to be recognized as such: + +@comment ignore +@example +define(`macro', `di$1') +macro(v)`'dnl +@end example + +@noindent +Without the quotes, this would rather yield the string @samp{divdnl} +followed by an end of line. + +Quoting may prevent recognizing as a macro name the concatenation of a +macro expansion with the surrounding characters. In this example: + +@comment ignore +@example +define(`macro', `di$1') +macro(v)`ert' +@end example + +@noindent +the input will produce the string @samp{divert}. If the quote was +removed, the @code{divert} builtin would be called instead. + +@node Macro Arguments, Quoting Arguments, Inhibiting Invocation, Macros +@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. If +there are too many arguments, the excess arguments are ignored. + +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 @samp{-Q} command line option. 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 + +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 leading unquoted whitespace is never part +of an argument, but trailing whitespace always is. + +@node Quoting Arguments, Macro expansion, Macro Arguments, Macros +@section Quoting macro arguments + +@cindex quoted macro arguments +@cindex macros, quoted arguments to +@cindex arguments, quoted macro +Each argument has leading unquoted whitespace removed. Within each +argument, all unquoted parentheses must match. For example, if +@var{foo} is a macro, + +@comment ignore +@example +foo(() (`(') `(') +@end example + +is a macro call, with one argument, whose value is @samp{()@w{ }(()@w{ }(}. + +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 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. + +@node Macro expansion, , Quoting Arguments, Macros +@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, Conditionals, Macros, Top +@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, which can be brought back at a later time. + +@menu +* Define:: Defining a new macro +* Arguments:: Arguments to macros +* Pseudo Arguments:: Pseudo 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, Arguments, Definitions, Definitions +@section Defining a macro + +@findex define +The normal way to define or redefine macros is to use the builtin +@code{define}: + +@comment ignore +@example +define(@var{name} [, @var{expansion}]) +@end example + +@noindent which 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 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 macro @code{define} is recognized only with parameters. + +@node Arguments, Pseudo Arguments, Define, Definitions +@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. Here is a 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. + +@cindex GNU extensions +GNU @code{m4} allows the number following the @samp{$} to consist of one +or more digits, allowing macros to have any number of arguments. This +is not so in UNIX implementations of @code{m4}, which only recognize +one digit. + +As a special case, the zero'th 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, Undefine, Arguments, Definitions +@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 +@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.. +echo2(foo) +@result{}This is macro foo. +@end example + +@noindent +@xref{Trace}, if you do not understand this. + +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}, put a pair +of quotes after the @code{$}. This will prevent @code{m4} from +interpreting the @code{$} sign as a reference to an argument. + +@node Undefine, Defn, Pseudo Arguments, Definitions +@section Deleting a macro + +@cindex macros, how to delete +@cindex deleting macros +@cindex undefining macros +@findex undefine +A macro definition can be removed with @code{undefine}: + +@comment ignore +@example +undefine(@var{name}) +@end example + +@noindent +which removes the macro @var{name}. The macro name must necessarily be +quoted, since it will be expanded otherwise. + +The expansion of @code{undefine} is void. + +@example +foo +@result{}foo +define(`foo', `expansion text') +@result{} +foo +@result{}expansion text +undefine(`foo') +@result{} +foo +@result{}foo +@end example + +It is not an error for @var{name} to have no macro definition. In that +case, @code{undefine} does nothing. + +The macro @code{undefine} is recognized only with parameters. + +@node Defn, Pushdef, Undefine, Definitions +@section Renaming macros + +@cindex macros, how to rename +@cindex renaming macros +@findex defn +It is possible to rename an already defined macro. To do this, you need +the builtin @code{defn}: + +@comment ignore +@example +defn(@var{name}) +@end example + +@noindent +which 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 ignored in any other context. + +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 macro @code{defn} is recognized only with parameters. + +@node Pushdef, Indir, Defn, Definitions +@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. +@findex popdef +@findex pushdef +This is done with the builtins @code{pushdef} and @code{popdef}: + +@comment ignore +@example +pushdef(@var{name} [, @var{expansion}]) +popdef(@var{name}) +@end example + +@noindent +which are quite 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}. + +@example +define(`foo', `Expansion one.') +@result{} +foo +@result{}Expansion one. +pushdef(`foo', `Expansion two.') +@result{} +foo +@result{}Expansion two. +popdef(`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 + +It is possible to temporarily redefine a builtin with @code{pushdef} +and @code{defn}. + +The macros @code{pushdef} and @code{popdef} are recognized only with +parameters. + +@node Indir, Builtin, Pushdef, Definitions +@section Indirect call of macros + +@cindex indirect call of macros +@cindex call of macros, indirect +@cindex macros, indirect call of +@cindex GNU extensions +@findex indir +Any macro can be called indirectly with @code{indir}: + +@comment ignore +@example +indir(@var{name}, ...) +@end example +@noindent +which results in a call to the macro @var{name}, which is passed the +rest of the arguments. This can be used to call macros with ``illegal'' +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}. + +@c FIXME: Why indir does not require at least one parameter? + +@node Builtin, , Indir, Definitions +@section Indirect call of builtins + +@cindex indirect call of builtins +@cindex call of builtins, indirect +@cindex builtins, indirect call of +@cindex GNU extensions +@findex builtin +Builtin macros can be called indirectly with @code{builtin}: + +@comment ignore +@example +builtin(@var{name}, ...) +@end example +@noindent +which results in a call to the builtin @var{name}, which is passed the +rest of the arguments. This can be used, if @var{name} has been given +another definition that has covered the original. + +The macro @code{builtin} is recognized only with parameters. + +@node Conditionals, Debugging, Definitions, Top +@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. E.g., 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 +* Loops:: Loops and recursion in m4 +@end menu + +@node Ifdef, Ifelse, Conditionals, Conditionals +@section Testing macro definitions + +@cindex conditionals +@findex ifdef +There are two different builtin conditionals in @code{m4}. The first is +@code{ifdef}: + +@comment ignore +@example +ifdef(@var{name}, @var{string-1}, opt @var{string-2}) +@end example + +@noindent +which makes it possible to test whether a macro is defined or not. 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). + +@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 +@end example + +The macro @code{ifdef} is recognized only with parameters. + +@node Ifelse, Loops, Ifdef, Conditionals +@section Comparing strings + +@cindex comparing strings +@findex ifelse +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: + +@comment ignore +@example +ifelse(@var{comment}) +ifelse(@var{string-1}, @var{string-2}, @var{equal}, opt @var{not-equal}) +ifelse(@var{string-1}, @var{string-2}, @var{equal}, ...) +@end example + +@noindent +Used with only one argument, the @code{ifelse} simply discards it and +produces no output. This is a common @code{m4} idiom for introducing a +block comment, as an alternative to repeatedly using @code{dnl}. This +special usage is recognized by GNU @code{m4}, so that in this case, the +warning about missing arguments is never triggered. + +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}. + +@example +ifelse(foo, bar, `true') +@result{} +ifelse(foo, foo, `true') +@result{}true +ifelse(foo, bar, `true', `false') +@result{}false +ifelse(foo, foo, `true', `false') +@result{}true +@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}, otherwise +the procedure is repeated with the first three arguments discarded. This +calls for an example: + +@example +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +@result{}seventh +@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. + +The macro @code{ifelse} is recognized only with parameters. + +@node Loops, , Ifelse, Conditionals +@section Loops and recursion + +@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. + +@findex shift +There is a builtin macro, @code{shift}, which can, among other things, +be used for iterating through the actual arguments to a macro: + +@comment ignore +@example +shift(...) +@end example + +@noindent +It takes any number of arguments, and expands to all but the first +argument, separated by commas, with each argument quoted. + +@example +shift(bar) +@result{} +shift(foo, bar, baz) +@result{}bar,baz +@end example + +An example of the use of @code{shift} is this macro, which reverses the +order of its arguments: + +@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. + +@cindex forloops +@cindex loops, counting +@cindex counting loops +Here is an example of a loop macro that implements a simple forloop. It +can, for example, be used for simple counting: + +@comment ignore +@example +forloop(`i', 1, 8, `i ') +@result{}1 2 3 4 5 6 7 8 +@end example + +The arguments are a name for the iteration variable, the starting value, +the final value, and the text to be expanded for each iteration. With +this macro, the macro @code{i} is defined only within the loop. After +the loop, it retains whatever value it might have had before. + +For-loops can be nested, like + +@comment ignore +@example +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{_forloop}, and re-establishes the saved definition of +the first argument. + +The macro @code{_forloop} expands the fourth argument once, and tests +to see if it is finished. If it has not finished, it increments +the iteration variable (using the predefined macro @code{incr}, +@pxref{Incr}), and recurses. + +Here is the actual implementation of @code{forloop}: + +@comment ignore +@example +define(`forloop', + `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') +define(`_forloop', + `$4`'ifelse($1, `$3', , + `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') +@end example + +Notice the careful use of quotes. Only three macro arguments are +unquoted, each for its own reason. Try to find out @emph{why} these +three arguments are left unquoted, and see what happens if they are +quoted. + +Now, even though these two macros are useful, they are still not robust +enough for general use. They lack even basic error handling of cases +like start value less than final value, and the first argument not being +a name. Correcting these errors are left as an exercise to the reader. + +@node Debugging, Input Control, Conditionals, Top +@chapter How to debug macros and input + +When writing macros for @code{m4}, most of the time they woould not +work as intended (as is the case with most programming languages). +There is a little 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, Trace, Debugging, Debugging +@section Displaying macro definitions + +@cindex displaying macro definitions +@cindex macros, displaying definitions +@cindex definitions, displaying macro +@findex dumpdef +If you want to see what a name expands into, you can use the builtin +@code{dumpdef}: + +@comment ignore +@example +dumpdef(...) +@end example + +@noindent +which 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 directly on +the standard error output. + +The expansion of @code{dumpdef} is void. + +@example +define(`foo', `Hello world.') +@result{} +dumpdef(`foo') +@error{}foo: `Hello world.' +@result{} +dumpdef(`define') +@error{}define: <define> +@result{} +@end example + +The last example shows how builtin macros definitions are displayed. + +@xref{Debug Levels} for information on controlling the details of the +display. + +@node Trace, Debug Levels, Dumpdef, Debugging +@section Tracing macro calls + +@cindex tracing macro expansion +@cindex macro expansion, tracing +@cindex expansion, tracing macro +@findex traceon +@findex traceoff +It is possible to trace macro calls and expansions through the builtins +@code{traceon} and @code{traceoff}: + +@comment ignore +@example +traceon(...) +traceoff(...) +@end example + +@noindent +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 named macros are affected. + +The expansion of @code{traceon} and @code{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 +directly on the standard error 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. + +@xref{Debug Levels} for information on controlling the details of the +display. + +@node Debug Levels, Debug Output, Trace, Debugging +@section Controlling debugging output + +@cindex controlling debugging output +@cindex debugging output, controlling +The @samp{-d} option to @code{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 t +Trace all macro calls made in this invocation of @code{m4}. + +@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 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 q +Quote actual arguments and macro expansions in the display with the +current quotes. + +@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 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 f +Show the name of the current input file in each trace output line. + +@item l +Show the 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 +mecanism (@pxref{Search Path}), giving the actual filename used. + +@item i +Print a message each time the current input file is changed, giving file +name and input line number. + +@item V +A shorthand for all of the above flags. +@end table + +If no flags are specified with the @samp{-d} option, the default is +@samp{aeq}. The examples in the previous two sections assumed the +default flags. + +@cindex GNU extensions +@findex debugmode +There is a builtin macro @code{debugmode}, which allows on-the-fly control of +the debugging output format: + +@comment ignore +@example +debugmode(opt @var{flags}) +@end example +@noindent +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, the debugging flags are set to +zero (as if no @samp{-d} was given), and with an empty argument the flags +are reset to the default. + +@node Debug Output, , Debug Levels, Debugging +@section Saving debugging output + +@cindex saving debugging output +@cindex debugging output, saving +@cindex output, saving debugging +@cindex GNU extensions +@findex debugfile +Debug and tracing output can be redirected to files using either the +@samp{-o} option to @code{m4}, or with the builtin macro @code{debugfile}: + +@comment ignore +@example +debugfile(opt @var{filename}) +@end example +@noindent +will send all further debug and trace output to @var{filename}. If +@var{filename} is empty, debug and trace output are discarded and if +@code{debugfile} is called without any arguments, debug and trace output +are sent to the standard error output. + +@node Input Control, File Inclusion, Debugging, Top +@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 input until end of input +@end menu + +@node Dnl, Changequote, Input Control, Input Control +@section Deleting whitespace in input + +@cindex deleting whitespace in input +@findex dnl +The builtin @code{dnl} reads and discards all characters, up to and +including the first newline: + +@comment ignore +@example +dnl +@end example +@noindent +and it is often used in connection with @code{define}, to remove the +newline that follow 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. 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. + +@node Changequote, Changecom, Dnl, Input Control +@section Changing the quote characters + +@cindex changing the quote delimiters +@cindex quote delimiters, changing the +@findex changequote +The default quote delimiters can be changed with the builtin +@code{changequote}: + +@comment ignore +@example +changequote(opt @var{start}, opt @var{end}) +@end example +@noindent +where @var{start} is the new start-quote delimiter and @var{end} is the +new end-quote delimiter. If any of the arguments are missing, the default +quotes (@code{`} and @code{'}) are used instead of the void arguments. + +The expansion of @code{changequote} is void. + +@example +changequote([, ]) +@result{} +define([foo], [Macro [foo].]) +@result{} +foo +@result{}Macro foo. +@end example + +If no single character is appropriate, @var{start} and @var{end} can be +of any length. + +@example +changequote([[, ]]) +@result{} +define([[foo]], [[Macro [[[foo]]].]]) +@result{} +foo +@result{}Macro [foo]. +@end example + +Changing the quotes to the empty strings will effectively disable the +quoting mechanism, leaving no way to quote text. + +@example +define(`foo', `Macro `FOO'.') +@result{} +changequote(, ) +@result{} +foo +@result{}Macro `FOO'. +`foo' +@result{}`Macro `FOO'.' +@end example + +There is no way in @code{m4} to quote a string containing an unmatched +left quote, except using @code{changequote} to change the current +quotes. + +Neither quote string should start with a letter or @samp{_} (underscore), +as they will be confused with names in the input. Doing so disables +the quoting mechanism. + +@node Changecom, Changeword, Changequote, Input Control +@section Changing comment delimiters + +@cindex changing comment delimiters +@cindex comment delimiters, changing +@findex changecom +The default comment delimiters can be changed with the builtin +macro @code{changecom}: + +@comment ignore +@example +changecom(opt @var{start}, opt @var{end}) +@end example +@noindent +where @var{start} is the new start-comment delimiter and @var{end} is +the new end-comment delimiter. If any of the arguments are void, the +default comment delimiters (@code{#} and newline) are used instead of +the void arguments. The comment delimiters can be of any length. + +The expansion of @code{changecom} is void. + +@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 +start comment delimiter. + +Calling @code{changecom} without any arguments disables the commenting +mechanism completely. + +@example +define(`comment', `COMMENT') +@result{} +changecom +@result{} +# Not a comment anymore +@result{}# Not a COMMENT anymore +@end example + +@node Changeword, M4wrap, Changecom, Input Control +@section Changing the lexical structure of words + +@cindex lexical structure of words +@cindex words, lexical structure of +@findex changeword +@quotation +The macro @code{changeword} and all associated functionnality is +experimental. It is only available if the @code{--enable-changeword} +option was given to @code{configure}, at GNU @code{m4} installation +time. The functionnality might change or even go away in the future. +@emph{Do not rely on it}. Please direct your comments about it the +same way you would do for bugs. +@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. Relaxing +@code{m4}'s lexical rules might be useful (for example) if you wanted to +apply translations to a file of numbers: + +@comment ignore +@example +changeword(`[_a-zA-Z0-9]+') +define(1, 0) +@result{}1 +@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: + +@comment ignore +@example +define(`_indir', defn(`indir')) +changeword(`_[_a-zA-Z0-9]*') +esyscmd(foo) +_indir(`esyscmd', `ls') +@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}. + +@code{changeword} has another function. If the regular expression +supplied contains any bracketed subexpressions, then text outside +the first of these is discarded before symbol lookup. So: + +@comment ignore +@example +changecom(`/*', `*/') +changeword(`#\([_a-zA-Z0-9]*\)') +#esyscmd(ls) +@end example + +@code{m4} now requires a @samp{#} mark at the beginning of every +macro invocation, so one can use @code{m4} to preprocess shell +scripts without getting @code{shift} commands swallowed, and plain +text without losing various common words. + +@code{m4}'s macro substitution is based on text, while @TeX{}'s 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 +@result{}@@a +@result{}@@bye +@end example + +@noindent +Then, the @code{m4} version: + +@comment ignore +@example +define(a, `errprint(`Hello')') +changeword(`@@\([_a-zA-Z0-9]*\)') +@result{}@@a +@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. + +@node M4wrap, , Changeword, Input Control +@section Saving input + +@cindex saving input +@cindex input, saving +@findex m4wrap +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}: + +@comment ignore +@example +m4wrap(@var{string}, ...) +@end example +@noindent +which stores @var{string} and the rest of the arguments in a safe place, +to be reread when end of input is reached. + +@example +define(`cleanup', `This is the `cleanup' actions. +') +@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 actions. +@end example + +The saved input is only reread when the end of normal input is seen, and +not if @code{m4exit} is used to exit @code{m4}. + +It is safe to call @code{m4wrap} from 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). + +@node File Inclusion, Diversions, Input Control, Top +@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, Search Path, File Inclusion, File Inclusion +@section Including named files + +@findex include +@findex sinclude +There are two builtin macros in @code{m4} for including files: + +@comment ignore +@example +include(@var{filename}) +sinclude(@var{filename}) +@end example + +@noindent +both of which cause the file named @var{filename} 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{filename}. + +It is an error for an @code{include}d file not to exist. If you do +not want error messages about non-existent files, @code{sinclude} can +be used to include a file, if it exists, expanding to nothing if it +does not. + +@example +include(`no-such-file') +@result{} +@error{}30.include:2: m4: Cannot open no-such-file: No such file or directory +sinclude(`no-such-file') +@result{} +@end example + +Assume in the following that the file @file{incl.m4} contains the lines: +@comment ignore +@example +Include file start +foo +Include file end +@end example +@noindent +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. + +The builtin macros @code{include} and @code{sinclude} are recognized +only when given arguments. + +@node Search Path, , Include, File Inclusion +@section Searching for include files + +@cindex search path for included files +@cindex included files, search path for +@cindex GNU extensions +GNU @code{m4} allows included files to be found in other directories +than the current working directory. + +If a file is not found in the current working directory, and the file +name is not absolute, the file will be looked for in a specified search +path. First, the directories specified with the @samp{-I} option will +be searched, in the order found on the command line. Second, if the +@samp{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, Text handling, File Inclusion, Top +@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 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. +So, it is theoretically possible that the number of diversions be +limited by the number of available file descriptors. + +@c FIXME: need some explanation here why this is a useful feature, not +@c just how you use it. + +@menu +* Divert:: Diverting output +* Undivert:: Undiverting output +* Divnum:: Diversion numbers +* Cleardiv:: Discarding diverted text +@end menu + +@node Divert, Undivert, Diversions, Diversions +@section Diverting output + +@cindex diverting output to files +@cindex output, diverting to files +@cindex files, diverting output to +@findex divert +Output is diverted using @code{divert}: + +@comment ignore +@example +divert(opt @var{number}) +@end example + +@noindent +where @var{number} is the diversion to be used. If @var{number} is left +out, it is assumed to be zero. + +The expansion of @code{divert} is void. + +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. + +If output is diverted to a non-existent 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 how to avoid them. + +@example +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +@result{} +@end example + +This is a common programming idiom in @code{m4}. + +@node Undivert, Divnum, Divert, Diversions +@section Undiverting output + +@findex undivert +Diverted text can be undiverted explicitly using the builtin +@code{undivert}: + +@comment ignore +@example +undivert(opt @var{number}, ...) +@end example + +@noindent +which undiverts the diversions given by the arguments, in the order +given. If no arguments are supplied, all diversions are undiverted, in +numerical order. + +@c FIXME: Explain what happens when undiverting all to else than 0. + +The expansion of @code{undivert} is void. + +@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. + +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. + +@cindex GNU extensions +@cindex file inclusion +@cindex inclusion, of files +GNU @code{m4} allows named files to be undiverted. Given a non-numeric +argument, the contents of the file named will be copied, uninterpreted, to +the current output. This complements the builtin @code{include} +(@pxref{Include}). To illustrate the difference, assume the file +@file{foo} contains the word @samp{bar}: + +@example +define(`bar', `BAR') +@result{} +undivert(`foo') +@result{}bar +@result{} +include(`foo') +@result{}BAR +@result{} +@end example + +@node Divnum, Cleardiv, Undivert, Diversions +@section Diversion numbers + +@cindex diversion numbers +@findex divnum +The builtin @code{divnum}: + +@comment ignore +@example +divnum +@end example + +@noindent +expands to the number of the current diversion. + +@example +Initial divnum +@result{}Initial 0 +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +@result{} +^D +@result{} +@result{}Diversion one: 1 +@result{} +@result{}Diversion two: 2 +@end example + +The last call of @code{divert} without argument is necessary, since the +undiverted text would otherwise be diverted itself. + +@node Cleardiv, , Divnum, Diversions +@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: + +@example +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@@)divert(_num)popdef(`_num')') +@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.) + +@node Text handling, Arithmetic, Diversions, Top +@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:: 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, Index, Text handling, Text handling +@section Calculating length of strings + +@cindex length of strings +@cindex strings, length of +@findex len +The length of a string can be calculated by @code{len}: + +@comment ignore +@example +len(@var{string}) +@end example + +@noindent +which expands to the length of @var{string}, as a decimal number. + +@example +len() +@result{}0 +len(`abcdef') +@result{}6 +@end example + +The builtin macro @code{len} is recognized only when given arguments. + +@node Index, Regexp, Len, Text handling +@section Searching for substrings + +@findex index +Searching for substrings is done with @code{index}: + +@comment ignore +@example +index(@var{string}, @var{substring}) +@end example + +@noindent +which 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}. + +@example +index(`gnus, gnats, and armadillos', `nat') +@result{}7 +index(`gnus, gnats, and armadillos', `dag') +@result{}-1 +@end example + +The builtin macro @code{index} is recognized only when given arguments. + +@node Regexp, Substr, Index, Text handling +@section Searching for regular expressions + +@cindex regular expressions +@cindex GNU extensions +@findex regexp +Searching for regular expressions is done with the builtin +@code{regexp}: + +@comment ignore +@example +regexp(@var{string}, @var{regexp}, opt @var{replacement}) +@end example + +@noindent +which searches for @var{regexp} in @var{string}. The syntax for regular +expressions is the same as in GNU Emacs. @xref{Regexps, , Syntax of +Regular Expressions, emacs, The GNU Emacs Manual}. + +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. + +@example +regexp(`GNUs not Unix', `\<[a-z]\w+') +@result{}5 +regexp(`GNUs not Unix', `\<Q\w*') +@result{}-1 +@end example + +If @var{replacement} is supplied, @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}, +@samp{\&} being the text the entire regular expression matched. + +@example +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +@result{}*** Unix *** nix *** +@end example + +The builtin macro @code{regexp} is recognized only when given arguments. + +@node Substr, Translit, Regexp, Text handling +@section Extracting substrings + +@cindex extracting substrings +@cindex substrings, extracting +@findex substr +Substrings are extracted with @code{substr}: + +@comment ignore +@example +substr(@var{string}, @var{from}, opt @var{length}) +@end example + +@noindent +which expands to the substring of @var{string}, which starts at index +@var{from}, and extends for @var{length} characters, or to the end of +@var{string}, if @var{length} is omitted. The starting index of a string +is always 0. + +@example +substr(`gnus, gnats, and armadillos', 6) +@result{}gnats, and armadillos +substr(`gnus, gnats, and armadillos', 6, 5) +@result{}gnats +@end example + +The builtin macro @code{substr} is recognized only when given arguments. + +@node Translit, Patsubst, Substr, Text handling +@section Translating characters + +@cindex translating characters +@cindex characters, translating +@findex translit +Character translation is done with @code{translit}: + +@comment ignore +@example +translit(@var{string}, @var{chars}, @var{replacement}) +@end example + +@noindent +which expands to @var{string}, with each character that occurs in +@var{chars} translated into the character from @var{replacement} with +the same index. + +If @var{replacement} is shorter than @var{chars}, the excess characters +are deleted from the expansion. If @var{replacement} is omitted, all +characters in @var{string}, that are present in @var{chars} are deleted +from the expansion. + +Both @var{chars} and @var{replacement} can contain character-ranges, +e.g., @samp{a-z} (meaning all lowercase letters) or @samp{0-9} (meaning +all digits). To include a dash @samp{-} in @var{chars} or +@var{replacement}, place it first or last. + +It is not an error for the last character in the range to be `larger' +than the first. In that case, the range runs backwards, i.e., +@samp{9-0} means the string @samp{9876543210}. + +@example +translit(`GNUs not Unix', `A-Z') +@result{}s not nix +translit(`GNUs not Unix', `a-z', `A-Z') +@result{}GNUS NOT UNIX +translit(`GNUs not Unix', `A-Z', `z-a') +@result{}tmfs not fnix +@end example + +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. + +The builtin macro @code{translit} is recognized only when given +arguments. + +@node Patsubst, Format, Translit, Text handling +@section Substituting text by regular expression + +@cindex regular expressions +@cindex pattern substitution +@cindex substitution by regular expression +@cindex GNU extensions +@findex patsubst +Global substitution in a string is done by @code{patsubst}: + +@comment ignore +@example +patsubst(@var{string}, @var{regexp}, opt @var{replacement}) +@end example +@noindent +which 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 GNU Emacs. + +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{regexp}, @samp{\&} +being the text the entire regular expression matched. + +The @var{replacement} argument can be omitted, in which case the text +matched by @var{regexp} is deleted. + +@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 +@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. + +@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 + +The builtin macro @code{patsubst} is recognized only when given +arguments. + +@node Format, , Patsubst, Text handling +@section Formatted output + +@cindex formatted output +@cindex output, formatted +@cindex GNU extensions +@findex format +Formatted output can be made with @code{format}: + +@comment ignore +@example +format(@var{format-string}, ...) +@end example + +@noindent +which works much like the C function @code{printf}. The first argument +is a format string, which can contain @samp{%} specifications, and the +expansion of @code{format} is the formatted string. + +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" is %d characters long', foo, len(foo)) +@result{}The string "The brown fox jumped over the lazy dog" is 38 characters long +@end example + +Using the @code{forloop} macro defined in @xref{Loops}, this +example shows how @code{format} can be used to produce tabular output. + +@comment ignore +@example +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 +@end example + +The builtin @code{format} is modeled after the ANSI C @samp{printf} +function, and supports the normal @samp{%} specifiers: @samp{c}, +@samp{s}, @samp{d}, @samp{o}, @samp{x}, @samp{X}, @samp{u}, @samp{e}, +@samp{E} and @samp{f}; 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. + +@c FIXME: Why format does not require at least one argument? + +@node Arithmetic, UNIX commands, Text handling, Top +@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, Eval, Arithmetic, Arithmetic +@section Decrement and increment operators + +@cindex decrement operator +@cindex increment operator +@findex incr +@findex decr +Increment and decrement of integers are supported using the builtins +@code{incr} and @code{decr}: + +@comment ignore +@example +incr(@var{number}) +decr(@var{number}) +@end example + +@noindent +which expand to the numerical value of @var{number}, incremented, +or decremented, respectively, by one. + +@example +incr(4) +@result{}5 +decr(7) +@result{}6 +@end example + +The builtin macros @code{incr} and @code{decr} are recognized only when +given arguments. + +@node Eval, , Incr, Arithmetic +@section Evaluating integer expressions + +@cindex integer expression evaluation +@cindex evaluation, of integer expressions +@cindex expressions, evaluation of integer +@findex eval +Integer expressions are evaluated with @code{eval}: + +@comment ignore +@example +eval(@var{expression}, opt @var{radix}, opt @var{width}) +@end example + +@noindent +which expands to the value of @var{expression}. + +Expressions can contain the following operators, listed in order of +decreasing precedence. + +@table @code +@item - +Unary 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 many @code{m4} implementations use @samp{^} as an alternate +operator for the exponentiation, while many others use @samp{^} for the +bitwise exclusive-or. GNU @code{m4} changed its behavior: it used to +exponentiate for @samp{^}, it now computes the bitwise exclusive-or. + +Numbers without special prefix are given decimal. A simple @samp{0} +prefix introduces an octal number. @samp{0x} introduces an 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 any radix, 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 +define(`square', `eval(($1)**2)') +@result{} +square(9) +@result{}81 +square(square(5)+1) +@result{}676 +define(`foo', `666') +@result{} +eval(`foo'/6) +@error{}51.eval:14: m4: Bad expression in eval: foo/6 +@result{} +eval(foo/6) +@result{}111 +@end example + +As the second to last example shows, @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}. + +If @var{radix} is specified, it specifies the radix to be used in the +expansion. The default radix is 10. The result of @code{eval} is +always taken to be signed. The @var{width} argument specifies a minimum +output width. The result is zero-padded to extend the expansion to the +requested width. + +@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{}-000003030 +@end example + +Take note that @var{radix} cannot be larger than 36. + +The builtin macro @code{eval} is recognized only when given arguments. + +@node UNIX commands, Miscellaneous, Arithmetic, Top +@chapter Running UNIX commands + +@cindex executing UNIX commands +@cindex running UNIX commands +@cindex UNIX commands, running +@cindex commands, running UNIX +There are a few builtin macros in @code{m4} that allow you to run UNIX +commands from within @code{m4}. + +@menu +* Syscmd:: Executing simple commands +* Esyscmd:: Reading the output of commands +* Sysval:: Exit codes +* Maketemp:: Making names for temporary files +@end menu + +@node Syscmd, Esyscmd, UNIX commands, UNIX commands +@section Executing simple commands + +@findex syscmd +Any shell command can be executed, using @code{syscmd}: + +@comment ignore +@example +syscmd(@var{shell-command}) +@end example + +@noindent +which 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 output buffers. +The default standard input, output and error of @var{shell-command} are +the same as those of @code{m4}. + +The builtin macro @code{syscmd} is recognized only when given arguments. + +@node Esyscmd, Sysval, Syscmd, UNIX commands +@section Reading the output of commands + +@findex esyscmd +@cindex GNU extensions +If you want @code{m4} to read the output of a UNIX command, use +@code{esyscmd}: + +@comment ignore +@example +esyscmd(@var{shell-command}) +@end example + +@noindent +which expands to the standard output of the shell command +@var{shell-command}. + +Prior to executing the command, @code{m4} flushes its output buffers. +The default standard input and error output 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}. + +Assume you are positioned into the @file{checks} directory of GNU +@code{m4} distribution, then: + +@example +define(`vice', `esyscmd(grep Vice ../COPYING)') +@result{} +vice +@result{} Ty Coon, President of Vice +@result{} +@end example + +Note how the expansion of @code{esyscmd} has a trailing newline. + +The builtin macro @code{esyscmd} is recognized only when given +arguments. + +@node Sysval, Maketemp, Esyscmd, UNIX commands +@section Exit codes + +@cindex exit code from UNIX commands +@cindex UNIX commands, exit code from +@cindex commands, exit code from UNIX +@findex sysval +To see whether a shell command succeeded, use @code{sysval}: + +@comment ignore +@example +sysval +@end example + +@noindent +which expands to the exit status of the last shell command run with +@code{syscmd} or @code{esyscmd}. + +@example +syscmd(`false') +@result{} +ifelse(sysval, 0, zero, non-zero) +@result{}non-zero +syscmd(`true') +@result{} +sysval +@result{}0 +@end example + +@node Maketemp, , Sysval, UNIX commands +@section Making names for temporary files + +@cindex temporary filenames +@cindex files, names of temporary +@findex maketemp +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{maketemp}, for making temporary file +names: + +@comment ignore +@example +maketemp(@var{template}) +@end example + +@noindent +which expands to a name of a non-existent file, made from the string +@var{template}, which should end with the string @samp{XXXXXX}. The six +@code{X}'s are then replaced, usually with something that includes the +process id of the @code{m4} process, in order to make the filename unique. + +@comment ignore +@example +maketemp(`/tmp/fooXXXXXX') +@result{}/tmp/fooa07346 +maketemp(`/tmp/fooXXXXXX') +@result{}/tmp/fooa07346 +@end example + +As seen in the example, several calls of @code{maketemp} might expand to +the same string, since the selection criteria is whether the file exists +or not. If a file has not been created before the next call, the two +macro calls might expand to the same name. + +The builtin macro @code{maketemp} is recognized only when given +arguments. + +@node Miscellaneous, Frozen files, UNIX commands, Top +@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 +* M4exit:: Exiting from m4 +@end menu + +@node Errprint, M4exit, Miscellaneous, Miscellaneous +@section Printing error messages + +@cindex printing error messages +@cindex error messages, printing +@cindex messages, printing error +@findex errprint +You can print error messages using @code{errprint}: + +@comment ignore +@example +errprint(@var{message}, ...) +@end example +@noindent +which simply prints @var{message} and the rest of the arguments on the +standard error output. + +The expansion of @code{errprint} is void. + +@example +errprint(`Illegal arguments to forloop +') +@error{}Illegal arguments to forloop +@result{} +@end example + +A trailing newline is @emph{not} printed automatically, so it must be +supplied as part of the argument, as in the example. (BSD flavored +@code{m4}'s do append a trailing newline on each @code{errprint} call). + +To make it possible to specify the location of the error, two +utility builtins exist: + +@findex file +@findex line +@comment ignore +@example +__file__ +__line__ +@end example +@noindent +which expands to the quoted name of the current input file, and the +current input line number in that file. + +@example +errprint(`m4:'__file__:__line__: `Input error +') +@error{}m4:56.errprint:2: Input error +@result{} +@end example + +@node M4exit, , Errprint, Miscellaneous +@section Exiting from @code{m4} + +@cindex exiting from @code{m4} +@findex m4exit +If you need to exit from @code{m4} before the entire input has been +read, you can use @code{m4exit}: + +@comment ignore +@example +m4exit(opt @var{code}) +@end example +@noindent +which causes @code{m4} to exit, with exit code @var{code}. If +@var{code} is left out, the exit code is zero. + +@example +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +@result{} +fatal_error(`This is a BAD one, buster') +@error{}m4: 57.m4exit: 5: fatal error: This is a BAD one, buster +@end example + +After this macro call, @code{m4} will exit with exit code 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. + +@node Frozen files, Compatibility, Miscellaneous, Top +@chapter Fast loading of frozen states + +@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 GNU extensions +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, @code{include}'d from this input file. + +Reading the common base of a big application, over and over again, may +be time consuming. GNU @code{m4} offers some machinery to speed up +the start of an application using lengthy common bases. Presume the +user repeatedly uses: + +@comment ignore +@example +m4 base.m4 input.m4 +@end example + +@noindent +with a varying contents of @file{input.m4}, but a rather fixed contents +for @file{base.m4}. Then, 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 input.m4 +@end example + +@noindent +with the varying input. The first call, containing the @code{-F} +option, only reads and executes file @file{base.m4}, so defining +various application macros and computing other initializations. Only +once the input file @file{base.m4} has been completely processed, 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 @code{-R} option, are able to reload +the internal state of @code{m4}'s memory, from @file{base.m4f}, +@emph{prior} to reading any other input files. By this mean, +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 +@code{-R} and @code{-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}. +Also, interactions for some options of @code{m4} being used in one call +and not for the next, have not been fully analyzed yet. On the other +end, you may be confident that stacks of @code{pushdef}'ed definitions +are handled correctly, so are @code{undefine}'d or renamed builtins, +changed strings for quotes or comments. + +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}). + +Frozen files are sharable across architectures. It is safe to write +a frozen file one one machine and read it on another, given that the +second machine uses the same, or a newer version of GNU @code{m4}. +These are simple (editable) text files, made up of directives, +each starting with a capital letter and ending with a newline +(@key{NL}). Wherever a directive is expected, the character +@kbd{#} introduces a comment line, empty lines are also ignored. +In the following descriptions, @var{length}s always refer to +corresponding @var{string}s. Numbers are always expressed in decimal. +The directives are: + +@table @code +@item V @var{number} @key{NL} +Confirms the format of the file. @var{number} should be 1. + +@item C @var{length1} , @var{length2} @key{NL} @var{string1} @var{string2} @key{NL} +Uses @var{string1} and @var{string2} as the beginning comment and +end comment strings. + +@item Q @var{length1} , @var{length2} @key{NL} @var{string1} @var{string2} @key{NL} +Uses @var{string1} and @var{string2} as the beginning quote and end quote +strings. + +@item F @var{length1} , @var{length2} @key{NL} @var{string1} @var{string2} @key{NL} +Defines, through @code{pushdef}, a definition for @var{string1} +expanding to the function whose builtin name is @var{string2}. + +@item T @var{length1} , @var{length2} @key{NL} @var{string1} @var{string2} @key{NL} +Defines, though @code{pushdef}, a definition for @var{string1} +expanding to the text given by @var{string2}. + +@item D @var{number}, @var{length} @key{NL} @var{string} @key{NL} +Selects diversion @var{number}, making it current, then copy +@var{string} 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{string}. With 0 as the +diversion @var{number}, @var{string} will be issued on standard output +at reload time, however this may not be produced from within @code{m4}. + +@end table + +@node Compatibility, Concept index, Frozen files, Top +@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 GNU m4 +* Incompatibilities:: Facilities in System V m4 not in GNU m4 +* Other Incompat:: Other incompatibilities +@end menu + +@node Extensions, Incompatibilities, Compatibility, Compatibility +@section Extensions in GNU @code{m4} + +@cindex 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 @samp{-G} command line option, 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 GNU @code{m4} to take any number of arguments, and +not only nine (@pxref{Arguments}). + +@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 @samp{-I} option and the +@samp{M4PATH} environment variable (@pxref{Search Path}). + +@item +Arguments to @code{undivert} can be non-numeric, in which case the named +file will be included uninterpreted in the output (@pxref{Undivert}). + +@item +Formatted output is supported through the @code{format} builtin, which +is modeled after the C library function @code{printf} (@pxref{Format}). + +@item +Searches and text substitution through regular expressions are +supported by the @code{regexp} (@pxref{Regexp}) and @code{patsubst} +(@pxref{Patsubst}) builtins. + +@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 current input file and the current input line number are +accessible through the builtins @code{__file__} and @code{__line__} +(@pxref{Errprint}). + +@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}). +@end itemize + +In addition to the above extensions, GNU @code{m4} implements the +following command line options: @samp{-F}, @samp{-G}, @samp{-I}, +@samp{-L}, @samp{-R}, @samp{-V}, @samp{-W}, @samp{-d}, +@samp{-l}, @samp{-o} and @samp{-t}. @xref{Invoking m4}, for a +description of these options. + +Also, the debugging and tracing facilities in GNU @code{m4} are much +more extensive than in most other versions of @code{m4}. + +@node Incompatibilities, Other Incompat, Extensions, Compatibility +@section Facilities in System V @code{m4} not in GNU @code{m4} + +The version of @code{m4} from System V contains a few facilities that +have not been implemented in GNU @code{m4} yet. + +@itemize @bullet +@item +System V @code{m4} supports multiple arguments to @code{defn}. This is +not implemented in GNU @code{m4}. Its usefulness is unclear to me. +@end itemize + +@node Other Incompat, , Incompatibilities, Compatibility +@section Other incompatibilities + +There are a few other incompatibilities between this implementation of +@code{m4}, and the System V version. + +@itemize @bullet +@item +GNU @code{m4} implements sync lines differently from System V @code{m4}, +when text is being diverted. GNU @code{m4} outputs the sync lines when +the text is being diverted, and System V @code{m4} when the diverted +text is being brought back. + +The problem is which lines and filenames should be attached to text that +is being, or has been, diverted. System V @code{m4} regards all the +diverted text as being generated by the source line containing the +@code{undivert} call, whereas GNU @code{m4} regards the diverted text as +being generated at the time it is diverted. + +I expect the sync line option to be 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 +GNU @code{m4} makes no attempt at prohiting autoreferential definitions +like: + +@comment ignore +@example +define(`x', `x') +define(`x', `x ') +@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 leave more rope +for the GNU @code{m4} user to hang himself! Rescanning hangs may be +avoided through careful programming, a little like for endless loops +in traditional programming languages. + +@item +@findex gnu +GNU @code{m4} without @samp{-G} option will define the macro +@code{__gnu__} to expand to the empty string. + +@findex unix +On UNIX systems, GNU @code{m4} without the @samp{-G} option will define +the macro @code{__unix__}, otherwise the macro @code{unix}. Both will +expand to the empty string. +@end itemize + +@node Concept index, Macro index, Compatibility, Top +@unnumbered Concept index + +@printindex cp + +@node Macro index, , Concept index, Top +@unnumbered Macro index + +References are exclusively to the places where a builtin is introduced +the first time. Names starting and ending with @samp{__} have these +characters removed in the index. + +@iftex +@sp 1 +@end iftex + +@printindex fn + +@summarycontents +@contents +@bye diff --git a/doc/mdate-sh b/doc/mdate-sh new file mode 100644 index 00000000..37171f21 --- /dev/null +++ b/doc/mdate-sh @@ -0,0 +1,92 @@ +#!/bin/sh +# Get modification time of a file or directory and pretty-print it. +# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Prevent date giving response in another language. +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_TIME=C +export LC_TIME + +# Get the extended ls output of the file or directory. +# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. +if ls -L /dev/null 1>/dev/null 2>&1; then + set - x`ls -L -l -d $1` +else + set - x`ls -l -d $1` +fi +# The month is at least the fourth argument +# (3 shifts here, the next inside the loop). +shift +shift +shift + +# Find the month. Next argument is day, followed by the year or time. +month= +until test $month +do + 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 + +day=$2 + +# 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 diff --git a/doc/stamp-vti b/doc/stamp-vti new file mode 100644 index 00000000..61e47e5d --- /dev/null +++ b/doc/stamp-vti @@ -0,0 +1 @@ +Sat Nov 5 22:46:26 EST 1994 diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 00000000..93bc18f6 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,4365 @@ +%% TeX macros to handle texinfo files + +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 1994 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, 675 Mass Ave, Cambridge, MA 02139, +%USA. + + +%In other words, you are welcome to use, share and improve this program. +%You are forbidden to forbid anyone else to use, share and improve +%what you give them. Help stamp out software-hoarding! + +% This automatically updates the version number based on RCS. +\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}} +\deftexinfoversion$Revision$ +\message{Loading texinfo package [Version \texinfoversion]:} + +% Print the version number if in a .fmt file. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{}} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptextilde=\~ +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexdots=\dots +\let\ptexdot=\. +\let\ptexstar=\* +\let\ptexend=\end +\let\ptexbullet=\bullet +\let\ptexb=\b +\let\ptexc=\c +\let\ptexi=\i +\let\ptext=\t +\let\ptexl=\l +\let\ptexL=\L + +% 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 + \gdef\tie{\leavevmode\penalty\@M\ } +} +\let\~ = \tie % And make it available as @~. + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English. +\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi% +\def\putwordInfo{Info}% +\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi% +\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi% +\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi% +\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi% +\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi% +\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi% +\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi% +\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi% +\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi% + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset \bindingoffset=0pt +\newdimen \normaloffset \normaloffset=\hoffset +\newdimen\pagewidth \newdimen\pageheight +\pagewidth=\hsize \pageheight=\vsize + +% 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. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% + +%---------------------Begin change----------------------- +% +%%%% For @cropmarks command. +% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\cornerlong \newdimen\cornerthick +\newdimen \topandbottommargin +\newdimen \outerhsize \newdimen \outervsize +\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks +\outerhsize=7in +%\outervsize=9.5in +% Alternative @smallbook page size is 9.25in +\outervsize=9.25in +\topandbottommargin=.75in +% +%---------------------End change----------------------- + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions itself, but you have to call it yourself. +\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}} +\def\onepageout#1{\hoffset=\normaloffset +\ifodd\pageno \advance\hoffset by \bindingoffset +\else \advance\hoffset by -\bindingoffset\fi +{\escapechar=`\\\relax % makes sure backslash is used in output files. +\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}% +{\let\hsize=\pagewidth \makefootline}}}% +\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi} + +%%%% For @cropmarks command %%%% + +% Here is a modification of the main output routine for Near East Publications +% This provides right-angle cropmarks at all four corners. +% The contents of the page are centerlined into the cropmarks, +% and any desired binding offset is added as an \hskip on either +% site of the centerlined box. (P. A. MacKay, 12 November, 1986) +% +\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up +{\escapechar=`\\\relax % makes sure backslash is used in output files. + \shipout + \vbox to \outervsize{\hsize=\outerhsize + \vbox{\line{\ewtop\hfill\ewtop}} + \nointerlineskip + \line{\vbox{\moveleft\cornerthick\nstop} + \hfill + \vbox{\moveright\cornerthick\nstop}} + \vskip \topandbottommargin + \centerline{\ifodd\pageno\hskip\bindingoffset\fi + \vbox{ + {\let\hsize=\pagewidth \makeheadline} + \pagebody{#1} + {\let\hsize=\pagewidth \makefootline}} + \ifodd\pageno\else\hskip\bindingoffset\fi} + \vskip \topandbottommargin plus1fill minus1fill + \boxmaxdepth\cornerthick + \line{\vbox{\moveleft\cornerthick\nsbot} + \hfill + \vbox{\moveright\cornerthick\nsbot}} + \nointerlineskip + \vbox{\line{\ewbot\hfill\ewbot}} + }} + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi} +% +% Do @cropmarks to get crop marks +\def\cropmarks{\let\onepageout=\croppageout } + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\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#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment. Type Return to continue.} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Type <Return> to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = 12.5pt +\def\singlespace{% + % Why was this kern here? It messes up equalizing space above and below + % environments. --karl, 6may93 + %{\advance \baselineskip by -\singlespaceskip + %\kern \baselineskip}% + \setleading \singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt \char '100}} + +% 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 \char '173}} +\def\myrbrace {{\tt \char '175}} +\let\{=\mylbrace +\let\}=\myrbrace + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @enddots{} is an end-of-sentence ellipsis. +\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000} + +% @! is an end-of-sentence bang. +\gdef\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\gdef\?{?\spacefactor=3000 } + +% @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. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below 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. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % 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 +} +% +% 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 + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\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\penalty 10000 +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\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 +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output some dots + +\def\dots{$\ldots$} + +% @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. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. + +\def\include{\parsearg\includezzz} +%Use \input\thisfile to avoid blank after \input, which may be an active +%char (in which case the blank would become the \input argument). +%The grouping keeps the value of \thisfile correct even when @include +%is nested. +\def\includezzz #1{\begingroup +\def\thisfile{#1}\input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\par \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{\catcode 64=\other \catcode 123=\other \catcode 125=\other% +\parsearg \commentxxx} + +\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } + +\let\c=\comment + +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% +\let\chapter=\relax +\let\unnumbered=\relax +\let\top=\relax +\let\unnumberedsec=\relax +\let\unnumberedsection=\relax +\let\unnumberedsubsec=\relax +\let\unnumberedsubsection=\relax +\let\unnumberedsubsubsec=\relax +\let\unnumberedsubsubsection=\relax +\let\section=\relax +\let\subsec=\relax +\let\subsubsec=\relax +\let\subsection=\relax +\let\subsubsection=\relax +\let\appendix=\relax +\let\appendixsec=\relax +\let\appendixsection=\relax +\let\appendixsubsec=\relax +\let\appendixsubsection=\relax +\let\appendixsubsubsec=\relax +\let\appendixsubsubsection=\relax +\let\contents=\relax +\let\smallbook=\relax +\let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax + \let\item = \relax + \let\message = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\ifhtml{\doignore{ifhtml}} +\def\html{\doignore{html}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + \long\def\doignoretext##1\end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % Similarly for index fonts (mostly for their use in + % smallexample) + \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont + \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont + \let\indsf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}} +} + +% @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. +% +\def\set{\parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi +} +\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +% +\def\value#1{\expandafter + \ifx\csname SET#1\endcsname\relax + {\{No value for ``#1''\}} + \else \csname SET#1\endcsname \fi} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex always succeeds; we read the text following, through @end +% iftex). But `@end iftex' should be valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\defineunmatchedend{iftex} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +\def\donoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\setref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\let\refill=\relax + +% @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{% + \readauxfile + \opencontents + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + \comment % Ignore the actual filename. +} + +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +\message{fonts,} + +% Font-change commands. + +% Texinfo supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +%% Try out Computer Modern fonts at \magstephalf +\let\mainmagstep=\magstephalf + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +\def\fontprefix{cm} +\def\setfont#1#2{\font#1=\fontprefix#2} + +% Enter `@setfontprefix dc' to use the dc fonts instead of the cm fonts. +\def\setfontprefix{\parsearg\\setfontprefixzzz} +\def\setfontprefixzzz#1{\gdef\fontprefix{#1}} + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\setfont\textrm{r12} +\setfont\texttt{tt12} +\else +\setfont\textrm{r10 scaled \mainmagstep} +\setfont\texttt{tt10 scaled \mainmagstep} +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\setfont\textbf{b10 scaled \mainmagstep} +\setfont\textit{ti10 scaled \mainmagstep} +\setfont\textsl{sl10 scaled \mainmagstep} +\setfont\textsf{ss10 scaled \mainmagstep} +\setfont\textsc{csc10 scaled \mainmagstep} +\setfont\texti{mi10 scaled \mainmagstep} +\setfont\textsy{sy10 scaled \mainmagstep} + +% A few fonts for @defun, etc. +\setfont\defbf{bx10 scaled \magstep1} %was 1314 +\setfont\deftt{tt10 scaled \magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples. +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\setfont\ninett{tt9} +\setfont\indrm{r9} +\setfont\indit{sl9} +\let\indsl=\indit +\let\indtt=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\let\indsc=\indrm +\setfont\indi{mi9} +\setfont\indsy{sy9} + +% Fonts for headings +\setfont\chaprm{bx12 scaled \magstep2} +\setfont\chapit{ti12 scaled \magstep2} +\setfont\chapsl{sl12 scaled \magstep2} +\setfont\chaptt{tt12 scaled \magstep2} +\setfont\chapsf{ss12 scaled \magstep2} +\let\chapbf=\chaprm +\setfont\chapsc{csc10 scaled\magstep3} +\setfont\chapi{mi12 scaled \magstep2} +\setfont\chapsy{sy10 scaled \magstep3} + +\setfont\secrm{bx12 scaled \magstep1} +\setfont\secit{ti12 scaled \magstep1} +\setfont\secsl{sl12 scaled \magstep1} +\setfont\sectt{tt12 scaled \magstep1} +\setfont\secsf{ss12 scaled \magstep1} +\setfont\secbf{bx12 scaled \magstep1} +\setfont\secsc{csc10 scaled\magstep2} +\setfont\seci{mi12 scaled \magstep1} +\setfont\secsy{sy10 scaled \magstep2} + +% \setfont\ssecrm{bx10 scaled \magstep1} % This size an font looked bad. +% \setfont\ssecit{cmti10 scaled \magstep1} % The letters were too crowded. +% \setfont\ssecsl{sl10 scaled \magstep1} +% \setfont\ssectt{tt10 scaled \magstep1} +% \setfont\ssecsf{ss10 scaled \magstep1} + +%\setfont\ssecrm{b10 scaled 1315} % Note the use of cmb rather than cmbx. +%\setfont\ssecit{ti10 scaled 1315} % Also, the size is a little larger than +%\setfont\ssecsl{sl10 scaled 1315} % being scaled magstep1. +%\setfont\ssectt{tt10 scaled 1315} +%\setfont\ssecsf{ss10 scaled 1315} + +%\let\ssecbf=\ssecrm + +\setfont\ssecrm{bx12 scaled \magstephalf} +\setfont\ssecit{ti12 scaled \magstephalf} +\setfont\ssecsl{sl12 scaled \magstephalf} +\setfont\ssectt{tt12 scaled \magstephalf} +\setfont\ssecsf{ss12 scaled \magstephalf} +\setfont\ssecbf{bx12 scaled \magstephalf} +\setfont\ssecsc{csc10 scaled \magstep1} +\setfont\sseci{mi12 scaled \magstephalf} +\setfont\ssecsy{sy10 scaled \magstep1} +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% Fonts for title page: +\setfont\titlerm{bx12 scaled \magstep3} +\let\authorrm = \secrm + +% 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, 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 so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current. Plain TeX does, for example, +% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need +% to redefine \bf itself. +\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 + \resetmathfonts} +\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 + \resetmathfonts} +\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 + \resetmathfonts} +\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 + \resetmathfonts} +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy + \resetmathfonts} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm{r12} +\setfont\shortcontbf{bx12} +\setfont\shortcontsl{sl12} + +%% 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\/\fi\fi\fi} +\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartitalic +\let\dfn=\smartitalic +\let\emph=\smartitalic +\let\cite=\smartitalic + +\def\b#1{{\bf #1}} +\let\strong=\b + +% 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 = `- } + +\def\t#1{% + {\tt \nohyphenation \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont = \t +%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null} +\def\samp #1{`\tclose{#1}'\null} +\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\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 + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overful 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 an a dash. +% -- rms. +{ +\catcode`\-=\active +\catcode`\_=\active +\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex} +% The following is used by \doprintindex to insure that long function names +% wrap around. It is necessary for - and _ to be active before the index is +% read from the file, as \entry parses the arguments long before \code is +% ever called. -- mycroft +\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder} +} +\def\realdash{-} +\def\realunder{_} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\normalunderscore\discretionary{}{}{}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +\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{\look}\fi +\else\tclose{\look}\fi} + +% 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} + +\def\l#1{{\li #1}\null} % + +\def\r#1{{\rm #1}} % roman font +% Use of \lowercase was suggested. +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\def\titlefont#1{{\titlerm #1}} + +\newif\ifseenauthor +\newif\iffinishedtitlepage + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm +% I deinstalled the following change because \cmr12 is undefined. +% This change was not in the ChangeLog anyway. --rms. +% \let\subtitlerm=\cmr12 + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefont{##1}} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % 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 + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\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 + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks \evenheadline % Token sequence for heading line of even pages +\newtoks \oddheadline % Token sequence for heading line of odd pages +\newtoks \evenfootline % Token sequence for footing line of even pages +\newtoks \oddfootline % Token sequence for footing line of 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\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish} +\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish} +\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} +% +}% unbind the catcode of @. + +% @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. + +\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{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +\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}} +} + +\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}} +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{\number\day\space +\ifcase\month\or +January\or February\or March\or April\or May\or June\or +July\or August\or September\or October\or November\or December\fi +\space\number\year} + +% Use this if you want the Month Day, Year style of output. +%\def\today{\ifcase\month\or +%January\or February\or March\or April\or May\or June\or +%July\or August\or September\or October\or November\or December\fi +%\space\number\day, \number\year} + +% @settitle line... specifies the title of the document, for headings +% It generates no output of its own + +\def\thistitle{No Title} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + +\message{tables,} + +% @tabs -- simple alignment + +% These don't work. For one thing, \+ is defined as outer. +% So these macros cannot even be defined. + +%\def\tabs{\parsearg\tabszzz} +%\def\tabszzz #1{\settabs\+#1\cr} +%\def\tabline{\parsearg\tablinezzz} +%\def\tablinezzz #1{\+#1\cr} +%\def\&{&} + +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(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, @vtable, 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\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % Be sure we are not still in the middle of a paragraph. + %{\parskip = 0in + %\par + %}% + % + % 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. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \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. Since that + % text will be indented by \tableindent, we make the item text be in + % a zero-width box. + \noindent + \rlap{\hskip -\tableindent\box0}\ignorespaces% + \endgroup% + \itemxneedsnegativevskiptrue% + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +%% Contains a kludge to get @end[description] to work +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Neccessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemsize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \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'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % 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 <number>. + % + \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 itemizey, 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 + \itemizey{#1.}\Eenumerate\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} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{\in hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94 +% +% @multitable ... @endmultitable 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 @percentofhsize .2 .3 .5 +% @item ... +% +% Numbers following @percentofhsize 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, @multicolumn or @endmulticolumn 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. +% @endmultitable + +% Default dimensions may be reset by user. +% @intableparskip will set vertical space between paragraphs in table. +% @intableparindent will set paragraph indent in table. +% @spacebetweencols will set horizontal space to be left between columns. +% @spacebetweenlines will set vertical space to be left between lines. + +%%%% +% Dimensions + +\newdimen\intableparskip +\newdimen\intableparindent +\newdimen\spacebetweencols +\newdimen\spacebetweenlines +\intableparskip=0pt +\intableparindent=6pt +\spacebetweencols=12pt +\spacebetweenlines=12pt + +%%%% +% Macros used to set up halign preamble: +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\percentofhsize\relax +\def\xpercentofhsize{\percentofhsize} +\newif\ifsetpercent + +\newcount\colcount +\def\setuptable#1{\def\firstarg{#1}% +\ifx\firstarg\xendsetuptable\let\go\relax% +\else + \ifx\firstarg\xpercentofhsize\global\setpercenttrue% + \else + \ifsetpercent + \if#1.\else% + \global\advance\colcount by1 % + \expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}% + \fi + \else + \global\advance\colcount by1 + \setbox0=\hbox{#1}% + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi% + \fi% + \let\go\setuptable% +\fi\go} +%%%% +% multitable syntax +\def\tab{&} + +%%%% +% @multitable ... @endmultitable definitions: + +\def\multitable#1\item{\bgroup +\let\item\cr +\tolerance=9500 +\hbadness=9500 +\parskip=\intableparskip +\parindent=\intableparindent +\overfullrule=0pt +\global\colcount=0\relax% +\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}% + % To parse everything between @multitable and @item : +\def\one{#1}\expandafter\setuptable\one\endsetuptable + % Need to reset this to 0 after \setuptable. +\global\colcount=0\relax% + % + % 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\relax% +\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % In order to keep entries from bumping into each other + % we will add a \leftskip of \spacebetweencols to all columns after + % the first one. + % If a template has been used, we will add \spacebetweencols + % to the width of each template entry. + % If 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. +\ifnum\colcount=1 +\else + \ifsetpercent + \else + % If user has <not> set preamble in terms of percent of \hsize + % we will advance \hsize by \spacebetweencols + \advance\hsize by \spacebetweencols + \fi + % In either case we will make \leftskip=\spacebetweencols: +\leftskip=\spacebetweencols +\fi +\noindent##}\cr% + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. +\global\everycr{\noalign{\nointerlineskip\vskip\spacebetweenlines +\filbreak%% keeps underfull box messages off when table breaks over pages. +\global\colcount=0\relax}}} + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \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{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @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. +\def\synindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#2}}% +} + +% 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}}} + +\def\indexdummies{% +% Take care of the plain tex accent commands. +\def\"{\realbackslash "}% +\def\`{\realbackslash `}% +\def\'{\realbackslash '}% +\def\^{\realbackslash ^}% +\def\~{\realbackslash ~}% +\def\={\realbackslash =}% +\def\b{\realbackslash b}% +\def\c{\realbackslash c}% +\def\d{\realbackslash d}% +\def\u{\realbackslash u}% +\def\v{\realbackslash v}% +\def\H{\realbackslash H}% +% Take care of the plain tex special European modified letters. +\def\oe{\realbackslash oe}% +\def\ae{\realbackslash ae}% +\def\aa{\realbackslash aa}% +\def\OE{\realbackslash OE}% +\def\AE{\realbackslash AE}% +\def\AA{\realbackslash AA}% +\def\o{\realbackslash o}% +\def\O{\realbackslash O}% +\def\l{\realbackslash l}% +\def\L{\realbackslash L}% +\def\ss{\realbackslash ss}% +% Take care of texinfo commands likely to appear in an index entry. +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\char{\realbackslash char}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\copyright{\realbackslash copyright }% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\t##1{\realbackslash r {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +% Just ignore accents. +\let\"=\indexdummyfont +\let\`=\indexdummyfont +\let\'=\indexdummyfont +\let\^=\indexdummyfont +\let\~=\indexdummyfont +\let\==\indexdummyfont +\let\b=\indexdummyfont +\let\c=\indexdummyfont +\let\d=\indexdummyfont +\let\u=\indexdummyfont +\let\v=\indexdummyfont +\let\H=\indexdummyfont +% Take care of the plain tex special European modified letters. +\def\oe{oe}% +\def\ae{ae}% +\def\aa{aa}% +\def\OE{OE}% +\def\AE{AE}% +\def\AA{AA}% +\def\o{o}% +\def\O{O}% +\def\l{l}% +\def\L{L}% +\def\ss{ss}% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other +@gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. + +\def\doind #1#2{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% Expand all macros now EXCEPT \folio +\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now +% so it will be output as is; and it will print as backslash in the indx. +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}}}% +\temp }% +}\penalty\count10}} + +\def\dosubind #1#2#3{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% +\def\rawbackslashxx{\indexbackslash}% +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2 #3}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}{#3}}}% +\temp }% +}\penalty\count10}} + +% 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. + +% This is what you call to cause a particular index to get printed. +% Write +% @unnumbered Function Index +% @printindex fn + +\def\printindex{\parsearg\doprintindex} + +\def\doprintindex#1{% + \tex + \dobreak \chapheadingskip {10000} + \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other + \catcode`\$=\other + \catcode`\~=\other + \indexbreaks + % + % The following don't help, since the chars were translated + % when the raw index was written, and their fonts were discarded + % due to \indexnofonts. + %\catcode`\"=\active + %\catcode`\^=\active + %\catcode`\_=\active + %\catcode`\|=\active + %\catcode`\<=\active + %\catcode`\>=\active + % % + \def\indexbackslash{\rawbackslashxx} + \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt + \begindoublecolumns + % + % See if the index file exists and is nonempty. + \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. + (Index is nonexistent) + \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 + (Index is empty) + \else + \input \jobname.#1s + \fi + \fi + \closein 1 + \enddoublecolumns + \Etex +} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +% Same as \bigskipamount except no shrink. +% \balancecolumns gets confused if there is any shrink. +\newskip\initialskipamount \initialskipamount 12pt plus4pt + +\def\initial #1{% +{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +\ifdim\lastskip<\initialskipamount +\removelastskip \penalty-200 \vskip \initialskipamount\fi +\line{\secbf#1\hfill}\kern 2pt\penalty10000}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry #1#2{\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 + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kluged 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{#2}% + \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. + \ #2% The page number ends the paragraph. + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \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 #2\par +}} + +%% Define two-column mode, which is used in indexes. +%% Adapted from the TeXbook, page 416. +\catcode `\@=11 + +\newbox\partialpage + +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup + % Grab any single-column material above us. + \output = {\global\setbox\partialpage + =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% + \eject + % + % Now switch to the double-column output routine. + \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 once. + % + % 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 + \doublecolumnpagegoal +} + +\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage} + +\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage + \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1} + \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3} + \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi + \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi +} +\def\doublecolumnpagegoal{% + \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@ +} +\def\pagesofar{\unvbox\partialpage % + \hsize=\doublecolumnhsize % have to restore this since output routine + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}} +\def\doublecolumnout{% + \setbox5=\copy255 + {\vbadness=10000 \doublecolumnsplit} + \ifvbox255 + \setbox0=\vtop to\dimen@{\unvbox0} + \setbox2=\vtop to\dimen@{\unvbox2} + \onepageout\pagesofar \unvbox255 \penalty\outputpenalty + \else + \setbox0=\vbox{\unvbox5} + \ifvbox0 + \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip + \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth + {\vbadness=10000 + \loop \global\setbox5=\copy0 + \setbox1=\vsplit5 to\dimen@ + \setbox3=\vsplit5 to\dimen@ + \ifvbox5 \global\advance\dimen@ by1pt \repeat + \setbox0=\vbox to\dimen@{\unvbox1} + \setbox2=\vbox to\dimen@{\unvbox3} + \global\setbox\partialpage=\vbox{\pagesofar} + \doublecolumnpagegoal + } + \fi + \fi +} + +\catcode `\@=\other +\message{sectioning,} +% Define chapters, sections, etc. + +\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} + +\newwrite \contentsfile +% This is called from \setfilename. +\def\opencontents{\openout \contentsfile = \jobname.toc} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise + +\def\thischapter{} \def\thissection{} +\def\seccheck#1{\if \pageno<0 % +\errmessage{@#1 not allowed after generating table of contents}\fi +% +} + +\def\chapternofonts{% +\let\rawbackslash=\relax% +\let\frenchspacing=\relax% +\def\result{\realbackslash result} +\def\equiv{\realbackslash equiv} +\def\expansion{\realbackslash expansion} +\def\print{\realbackslash print} +\def\TeX{\realbackslash TeX} +\def\dots{\realbackslash dots} +\def\copyright{\realbackslash copyright} +\def\tt{\realbackslash tt} +\def\bf{\realbackslash bf } +\def\w{\realbackslash w} +\def\less{\realbackslash less} +\def\gtr{\realbackslash gtr} +\def\hat{\realbackslash hat} +\def\char{\realbackslash char} +\def\tclose##1{\realbackslash tclose {##1}} +\def\code##1{\realbackslash code {##1}} +\def\samp##1{\realbackslash samp {##1}} +\def\r##1{\realbackslash r {##1}} +\def\b##1{\realbackslash b {##1}} +\def\key##1{\realbackslash key {##1}} +\def\file##1{\realbackslash file {##1}} +\def\kbd##1{\realbackslash kbd {##1}} +% These are redefined because @smartitalic wouldn't work inside xdef. +\def\i##1{\realbackslash i {##1}} +\def\cite##1{\realbackslash cite {##1}} +\def\var##1{\realbackslash var {##1}} +\def\emph##1{\realbackslash emph {##1}} +\def\dfn##1{\realbackslash dfn {##1}} +} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/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 + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + + +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{\seccheck{chapter}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{Chapter \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{\seccheck{appendix}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 \message{Appendix \appendixletter}% +\chapmacro {#1}{\putwordAppendix{} \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry + {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +\outer\def\top{\parsearg\unnumberedyyy} +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{\seccheck{unnumbered}% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% 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<toks register> to achieve this: TeX expands \the<toks> only once, +% simply yielding the contents of the <toks register>. +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +}} + +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{\seccheck{section}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appenixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{\seccheck{appendixsection}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{\seccheck{subsection}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry % + {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} + {\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry{#1}% + {\appendixletter} + {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% 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. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\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{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\heading{\parsearg\secheadingi} + +\def\subheading{\parsearg\subsecheadingi} + +\def\subsubheading{\parsearg\subsubsecheadingi} + +% 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} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt + +\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\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain} + +\def\chfplain #1#2{% + \pchapsepmacro + {% + \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #2\enspace #1}% + }% + \bigskip + \penalty5000 +} + +\def\unnchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\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\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen} + +% Parameter controlling skip before section headings. + +\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} + +\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Section fonts are the base font at magstep2, which produces +% a size a bit more than 14 points in the default situation. + +\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} +\def\plainsecheading #1{\secheadingi {#1}} +\def\secheadingi #1{{\advance \secheadingskip by \parskip % +\secheadingbreak}% +{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + +% Subsection fonts are the base font at magstep1, +% which produces a size of 12 points. + +\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}} +\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + +\def\subsubsecfonts{\subsecfonts} % Maybe this should change: + % Perhaps make sssec fonts scaled + % magstep half +\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}} +\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} + + +\message{toc printing,} + +% Finish up the main text and prepare to read what we've written +% to \contentsfile. + +\newskip\contentsrightmargin \contentsrightmargin=1in +\def\startcontents#1{% + \pagealignmacro + \immediate\closeout \contentsfile + \ifnum \pageno>0 + \pageno = -1 % Request roman numbered pages. + \fi + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. +} + + +% Normal (long) toc. +\outer\def\contents{% + \startcontents{\putwordTableofContents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{\putwordShortContents}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \endgroup + \vfill \eject +} +\let\shortcontents = \summarycontents + +% 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, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm \putwordAppendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in in \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% 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 would want to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +% +\def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{#1}{#2}% +\endgroup} + +% 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} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% 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. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +\let\ptexequiv = \equiv + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +\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}} + +% Adapted from the TeXbook's \boxit. +{\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 \tensf error\kern-1.5pt} + +\global\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} + +% The @error{} command. +\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. + +\def\tex{\begingroup +\catcode `\\=0 \catcode `\{=1 \catcode `\}=2 +\catcode `\$=3 \catcode `\&=4 \catcode `\#=6 +\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie +\catcode `\%=14 +\catcode 43=12 +\catcode`\"=12 +\catcode`\==12 +\catcode`\|=12 +\catcode`\<=12 +\catcode`\>=12 +\escapechar=`\\ +% +\let\~=\ptextilde +\let\{=\ptexlbrace +\let\}=\ptexrbrace +\let\.=\ptexdot +\let\*=\ptexstar +\let\dots=\ptexdots +\def\@{@}% +\let\bullet=\ptexbullet +\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl +\let\L=\ptexL +% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (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} + +% 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. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% 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{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \cartouche: draw rectangle w/rounded corners around argument +\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 + +\long\def\cartouche{% +\begingroup + \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 18pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \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 + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% To ending an @example-like environment, we first end the paragraph +% (via \afterenvbreak's vertical glue), and then the group. That way we +% keep the zero \parskip that the environments set -- \parskip glue +% will be inserted at the beginning of the next paragraph in the +% document, after the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup}% + +% This macro is +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \rawbackslash % have \ input char produce \ char from current font + \gobble +} + +% Define the \E... control sequence only if we are inside the +% environment, so the error checking in \end will work. +% +% We must call \lisp last in the definition, since it reads the +% return following the @example (or whatever) command. +% +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp. This is not used unless the @smallbook +% command is given. Originally contributed by Pavel@xerox. +% +\def\smalllispx{\begingroup + \nonfillstart + \let\Esmalllisp = \nonfillfinish + \let\Esmallexample = \nonfillfinish + % + % Smaller interline space and fonts for small examples. + \setleading{10pt}% + \indexfonts \tt + \rawbackslash % make \ output the \ character from the current font (tt) + \gobble +} + +% This is @display; same as @lisp except use roman font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% This is @format; same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @flushleft (same as @format) and @flushright. +% +\def\flushleft{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushleft = \nonfillfinish + \gobble +} +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \singlespace + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\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 = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% 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. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested % +\global\advance\parencount by 1 } +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. +% also in that case restore the outer-level definition of (. +\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi +\global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\dimen3=\rightskip +\advance\dimen3 by -\defbodyindent +\noindent % +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 % +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 +\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +\def\defmethparsebody #1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does, putting the result in \tptemp. +% +\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}% + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + \removeemptybraces#2\relax + #1{\tptemp}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0 +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\functionparens +\tclose{#1}% avoid \code because of side effects on active chars +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Function}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$$$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$$$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Macro}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Special Form}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}} + +% @defmethod, and so on + +% @defop {Funny Method} foo-class frobnicate argument + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype{} on #1}% +\defunargs {#3}\endgroup % +} + +% @defmethod == @defop Method + +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} + +\def\defmethodheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% entry in function index +\begingroup\defname {#2}{Method on #1}% +\defunargs {#3}\endgroup % +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype{} of #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{Instance Variable of #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{Variable}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{User Option}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name. +\def\deftypevarheader #1#2{% +\doind {vr}{\code{#2}}% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}% +\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + +\message{cross reference,} +% Define cross-reference macros +\newwrite \auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% \setref{foo} defines a cross-reference point named foo. + +\def\setref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ysectionnumberandtype}} + +\def\unnumbsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ynothing}} + +\def\appendixsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Yappendixletterandtype}} + +% \xref, \pxref, and \ref generate cross-references to specified points. +% 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 + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \ifx\SETxref-automatic-section-title\relax % + % 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\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \def\printednodename{#1-title}% + \else + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \fi + \fi + % + % 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{} ``\printednodename'' in \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 \refx{#1-snt}{}}% + \space [\printednodename],\space + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \turnoffactive so that punctuation chars such as underscore +% work in node names. +\def\dosetq #1#2{{\let\folio=0 \turnoffactive% +\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}% +\next}} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% 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 % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\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{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + $\langle$un\-de\-fined$\rangle$% + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% Read the last existing aux file, if any. No error if none exists. + +% This is the macro invoked by entries in the aux file. +\def\xrdef #1#2{ +{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}} + +\def\readauxfile{% +\begingroup +\catcode `\^^@=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\^^C=\other +\catcode `\^^D=\other +\catcode `\^^E=\other +\catcode `\^^F=\other +\catcode `\^^G=\other +\catcode `\^^H=\other +\catcode `\=\other +\catcode `\^^L=\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 +\catcode 26=\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 +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode `\$=\other +\catcode `\#=\other +\catcode `\&=\other +% `\+ does not work, so use 43. +\catcode 43=\other +% Make the characters 128-255 be printing characters +{% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% +}% +% the aux file uses ' as the escape. +% Turn off \ as an escape so we do not lose on +% entries which were dumped with control sequences in their names. +% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ +% Reference to such entries still does not work the way one would wish, +% but at least they do not bomb out when the aux file is read in. +\catcode `\{=1 \catcode `\}=2 +\catcode `\%=\other +\catcode `\'=0 +\catcode `\\=\other +\openin 1 \jobname.aux +\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue +\global\warnedobstrue +\fi +% Open the new aux file. Tex will close it automatically at exit. +\openout \auxfile=\jobname.aux +\endgroup} + + +% 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. +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only.. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \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}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% 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. +% +\long\gdef\footnotezzz#1{\insert\footins{% + % 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. + \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 + % + % Hang the footnote text off the number. + \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 + #1\strut}% +} + +}%end \catcode `\@=11 + +% 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 + }% +} + +% @| 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 + }% + }% +} + +% 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} + + +% End of control word definitions. + +\message{and turning on texinfo input format.} + +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% Set some numeric style parameters, for 8.5 x 11 format. + +%\hsize = 6.5in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 18pt plus 1pt +\setleading{15pt} +\advance\topskip by 1.2cm + +% Prevent underfull vbox error messages. +\vbadness=10000 + +% 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. This makes it come to about 9pt for the 8.5x11 format. +% +\ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% +\else + \emergencystretch = \hsize + \divide\emergencystretch by 45 +\fi + +% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) +\def\smallbook{ + +% These values for secheadingskip and subsecheadingskip are +% experiments. RJC 7 Aug 1992 +\global\secheadingskip = 17pt plus 6pt minus 3pt +\global\subsecheadingskip = 14pt plus 6pt minus 3pt + +\global\lispnarrowing = 0.3in +\setleading{12pt} +\advance\topskip by -1cm +\global\parskip 3pt plus 1pt +\global\hsize = 5in +\global\vsize=7.5in +\global\tolerance=700 +\global\hfuzz=1pt +\global\contentsrightmargin=0pt +\global\deftypemargin=0pt +\global\defbodyindent=.5cm + +\global\pagewidth=\hsize +\global\pageheight=\vsize + +\global\let\smalllisp=\smalllispx +\global\let\smallexample=\smalllispx +\global\def\Esmallexample{\Esmalllisp} +} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{ +\global\tolerance=700 +\global\hfuzz=1pt +\setleading{12pt} +\global\parskip 15pt plus 1pt + +\global\vsize= 53\baselineskip +\advance\vsize by \topskip +%\global\hsize= 5.85in % A4 wide 10pt +\global\hsize= 6.5in +\global\outerhsize=\hsize +\global\advance\outerhsize by 0.5in +\global\outervsize=\vsize +\global\advance\outervsize by 0.6in + +\global\pagewidth=\hsize +\global\pageheight=\vsize +} + +% Allow control of the text dimensions. Parameters in order: textheight; +% textwidth; \voffset; \hoffset (!); binding offset. All require a dimension; +% header is additional; added length extends the bottom of the page. + +\def\changepagesizes#1#2#3#4#5 +{\global\vsize= #1 + \advance\vsize by \topskip + \global\voffset= #3 + \global\hsize= #2 + \global\outerhsize=\hsize + \global\advance\outerhsize by 0.5in + \global\outervsize=\vsize + \global\advance\outervsize by 0.6in + \global\pagewidth=\hsize + \global\pageheight=\vsize + \global\normaloffset= #4 + \global\bindingoffset= #5} + +% This layout is compatible with Latex on A4 paper. + +\def\afourlatex{\changepagesizes{22cm}{15cm}{7mm}{4.6mm}{5mm}} + +% 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 +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, 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\the\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 \char '042}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt \char '176}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +% \lvvmode is equivalent in function to \leavevmode. +% Using \leavevmode runs into trouble when written out to +% an index file due to the expansion of \leavevmode into ``\unhbox +% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our +% magic tricks with @. +\def\lvvmode{\vbox to 0pt{}} + +\catcode`\|=\active +\def|{{\tt \char '174}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{@let"=@normaldoublequote +@let\=@realbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +% 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. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi} + +%% These look ok in all fonts, so just make them not special. The @rm below +%% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c page-delimiter: "^\\\\message" +@c End: diff --git a/doc/version.texi b/doc/version.texi new file mode 100644 index 00000000..b55168ee --- /dev/null +++ b/doc/version.texi @@ -0,0 +1,3 @@ +@set EDITION 1.4 +@set UPDATED November 1994 +@set VERSION 1.4 diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 00000000..8b96545b --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,5 @@ +EXTRA_DIST = capitalize.m4 comments.m4 ddivert.m4 \ +debug.m4 esyscmd.m4 exp.m4 file.m4 foreach.m4 forloop.m4 fstab.m4 \ +hanoi.m4 incl-test.m4 include.m4 indir.m4 misc.m4 multiquotes.m4 \ +patsubst.m4 pushpop.m4 regexp.m4 reverse.m4 stackovf.sh sync-lines.m4 \ +sysv-args.m4 trace.m4 translit.m4 undivert.incl undivert.m4 wrap.m4 diff --git a/examples/Makefile.in b/examples/Makefile.in new file mode 100644 index 00000000..47e6fe16 --- /dev/null +++ b/examples/Makefile.in @@ -0,0 +1,60 @@ +# Makefile for GNU m4 examples. +# Copyright (C) 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +PRODUCT = @PRODUCT@ +VERSION = @VERSION@ + +SHELL = /bin/sh +srcdir = @srcdir@ +VPATH = @srcdir@ + +.SUFFIXES: + +DISTFILES = Makefile.in capitalize.m4 comments.m4 ddivert.m4 \ +debug.m4 esyscmd.m4 exp.m4 file.m4 foreach.m4 forloop.m4 fstab.m4 \ +hanoi.m4 incl-test.m4 include.m4 indir.m4 misc.m4 multiquotes.m4 \ +patsubst.m4 pushpop.m4 regexp.m4 reverse.m4 stackovf.sh sync-lines.m4 \ +sysv-args.m4 trace.m4 translit.m4 undivert.incl undivert.m4 wrap.m4 + +all: + +install: + +uninstall: + +mostlyclean: + +clean: mostlyclean + +distclean: clean + rm -f Makefile + +realclean: distclean + +dist: $(DISTFILES) + @echo "Copying distribution files" + @for file in $(DISTFILES); do \ + ln $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/examples 2> /dev/null \ + || cp -p $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/examples; \ + done + +Makefile: Makefile.in ../config.status + cd .. && CONFIG_FILES=examples/$@ CONFIG_HEADERS= ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/examples/WWW/Makefile b/examples/WWW/Makefile new file mode 100644 index 00000000..f143493e --- /dev/null +++ b/examples/WWW/Makefile @@ -0,0 +1,18 @@ +M4 = m4 +M4OPTS = -Im4lib + +VPATH = .:m4lib + +all: *.htm + +%.htm: %.m4 + @$(M4) $(M4OPTS) $< >new.htm && \ + if cmp -s new.htm $@; then \ + rm new.htm; \ + echo "$@ has not changed"; \ + else \ + echo "$@ updated"; \ + mv new.htm $@; \ + fi + +*.htm: m4lib/*.m4 diff --git a/examples/WWW/_footer.htm b/examples/WWW/_footer.htm new file mode 100644 index 00000000..8fbbce61 --- /dev/null +++ b/examples/WWW/_footer.htm @@ -0,0 +1,15 @@ + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/_header.htm b/examples/WWW/_header.htm new file mode 100644 index 00000000..643223d6 --- /dev/null +++ b/examples/WWW/_header.htm @@ -0,0 +1,234 @@ +<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Development site</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4o"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=middle colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Discussion Forum</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + + + + + + + + + +<TABLE > +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>General info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/whatis.htm">What is m4</A><BR> +<A HREF="/rene/gnu/features.htm">Features</A><BR> +<A HREF="/rene/gnu/uses.htm">Uses of m4</A></B></FONT> + +</P> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/man/m4_toc.html">Manual</A></B></FONT> + +</P> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/readme.htm">README</A><BR> +<A HREF="/rene/gnu/todo.htm">TODO</A><BR> +<A HREF="/rene/gnu/news.htm">NEWS</A><BR> +<A HREF="/rene/gnu/changelog.htm">ChangeLog</A><BR> +<A HREF="/rene/gnu/thanks.htm">Contributors</A><BR> +<A HREF="/rene/gnu/m4/">Browse it</A></B></FONT> + +</P> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/modules.htm">Modules</A><BR> +<A HREF="/rene/gnu/visions.htm">Visions</A></B></FONT> + +</P> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Feedback</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/lists.htm">Mailing-lists</A><BR> +<A HREF="/rene/gnu/feedback.htm">Feedback</A><BR> + +</P> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/download.htm">Download</A><BR> +<A HREF="/rene/gnu/bugs.htm">Known bugs</A></B></FONT> + +</P> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> +<P> + +<FONT size=-1><B><A HREF="/rene/gnu/thissite.htm">This site</A></B></FONT> + +</P> + +</TD> + +</TR> + +</TABLE> + + + + + + + + +</TD> + <TD align=left valign=top width="90%"> + + + diff --git a/examples/WWW/bugs.htm b/examples/WWW/bugs.htm new file mode 100644 index 00000000..207fcc31 --- /dev/null +++ b/examples/WWW/bugs.htm @@ -0,0 +1,284 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Known bugs in GNU m4 \__m4_version__</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4n"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Known bugs in GNU m4 1.4n</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + + + + + + + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A><BR> +<A HREF="features.htm">Features</A><BR> +<A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A><BR> +<A HREF="todo.htm">TODO</A><BR> +<A HREF="news.htm">NEWS</A><BR> +<A HREF="changelog.htm">ChangeLog</A><BR> +<A HREF="thanks.htm">Contributors</A><BR> +<A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A><BR> +<A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A><BR> +<A HREF="feedback.htm">Feedback</A><BR> +<A HREF="download.htm">Download</A><BR> +<A HREF="bugs.htm">Known bugs</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD height=5> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<H2>Known bugs in GNU m4</H2> + + + + + + +<UL> + + +<LI> <A HREF="#undivert">undivert(0) might read from standard output.</A> + + + + +<LI> <A HREF="#sigaltstack">failure if sigaltstack or sigstack returns ENOSYS.</A> + + + + + +</UL> + + +<P> +See also the <A HREF="todo.htm">TODO</A> file. +</P> + + + +<HR align=center width=50%><A NAME="undivert"> +<H2>undivert(0) might read from standard output</H2> +</A><P> +If calling <TT>undivert(0)</TT> when diverting to a non-zero diversion +will cause m4 to read from standard output in an attempt to bring back +diversion 0, which is not possible. +</P> + + +<P> +Fixed in version 1.4n +</P> + + + +<HR align=center width=50%><A NAME="sigaltstack"> +<H2>failure if sigaltstack or sigstack returns ENOSYS</H2> +</A><P> +If stack overflow detection is configured but the system doesn't +support sigaltstack(2) or sigstack(2), m4 fails when the system call +returns ENOSYS. It should silently revert to default behaviour. +</P> + + +<P> +A <A +HREF="mailto:m4-feedback@seindal.dk?subject=GNU m4: failure if sigaltstack or sigstack returns ENOSYS" +>volunteer</A> is badly needed for this, as I have no way of testing +this myself. +</P> + + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/changelog.htm b/examples/WWW/changelog.htm new file mode 100644 index 00000000..56713edc --- /dev/null +++ b/examples/WWW/changelog.htm @@ -0,0 +1,2248 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - ChangeLog</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>ChangeLog</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<PRE>1998-11-18 Rene' Seindal <rene@seindal.dk> + + * src/input.c (set_word_regexp): Fixed a bug, where word_regexp + could be changed when compiling a illegal regexp, causing later + use of the regexp to dump core. + + * src/module.c (module_load): Changed error message to conform to + standards. + + * src/m4.c (usage): Added message about reporting bugs. + + * doc/m4.texinfo (Changeword): Corrected a wrong example. + (Changeword): Added note about the type of regexps used. + + * ltconfig, ltmain.sh: New files from Libtool 1.2. + + * configure.in: Added calls to AM_ENABLE_SHARED, AM_DISABLE_STATIC + and AM_PROG_LIBTOOL. + + * acm4/modules.m4 (AM_WITH_MODULES): Redone completely to work + with libtool. + + * modules/Makefile.am: Changed completely to compile modules using + libtool. The modules are compiled as shared libraries, and are + renamed when installed. + + * src/m4.h, src/module.c, acm4/modules.m4, acconfig.h: Renamed + USE_SHL_LOAD to HAVE_SHL_LOAD + + * src/builtin.c (shipout_string): Now tests for a NULL string. + + * src/module.c: New level of indirection around non-portable + functions to load shared objects. Intended to encapsulate the non + portable parts better and to reduce the number of #ifdefs in the + code. + + * Makefile.am (DIST_SUBDIRS): Instead of EXTRA_DIST for added + directory modules/ to the distribution. + +1998-11-15 Rene' Seindal <rene@seindal.dk> + + * Prerelease 1.4l. + + * modules/stdlib.c: New module `stdlib' defining some standard + functions: getcwd, getlogin, getpid, getppid, getuid, getpwnam, + getpwuid, hostname, rand, srand, getenv, setenv, unsetenv, uname. + + * src/builtin.c (shipout_string): New convenience function for + builtins and modules. + + * src/module.c (module_load): Tentative support for + shl_load/shl_findsym, but I cannot test it. Copied from MetaHTML. + + * Makefile.am (SUBDIRS): Directory modules added if configured. + + * modules/Makefile.am: Now correctly compiles and installs + modules in pkglibexecdir. + + * src/m4.h: WITH_MODULES defined iff HAVE_DLOPEN or USE_SHL_LOAD. + These two are now initialised by autoconf macros. + + * src/path.c (module_env_init): MODULE_PATH is always on the + search path. + + * src/Makefile.am: Now generated pathconf.h which defined the + default MODULE_PATH. + + * configure.in (pkglibexecdir): Added defintion of pkglibexecdir, + where modules are installed. + + * acm4/modules.m4: Enhanced with code from MetaHTML, contributed + by Brian J. Fox <bfox@datawave.net>. This change allow modules to + build and install automatically, and it is prepared for other + interfacec than dlopen(). + + * src/builtin.c (predefined_tab): Added __m4_version__ for the + current version of GNU m4. It is a GNU extension. + +1998-11-14 Rene' Seindal <rene@seindal.dk> + + * tests/Makefile.am (GENERATED_TESTS): Added new + generated-tests/changesy.8.test + + * doc/m4.texinfo (Changesyntax): Documentation for escape + syntax class. + + * src/macro.c (expand_token): Check for escaped macro call before + symbol table lookup. + + * src/builtin.c (m4_changesyntax): Added `@' flag to define escape + characters + + * src/input.c: New static variable use_macro_escape, which is TRUE + iff some character has code SYNTAX_ESCAPE + (input_init): Added initialisation of use_macro_escape. + (check_use_macro_escape): New function to synchronise + use_macro_escape with the syntax table. + (set_quotes): Added call to check_use_macro_escape() + (set_comment): Do. + (set_syntax): Do. + (next_token): Added new case for IS_ESCAPE. + + * src/m4.h (SYNTAX_ESCAPE): Defined as simple syntax category. + +1998-10-13 René Seindal <rene@seindal.dk> + + * Prerelease 1.4k. + + * tests/Makefile.am (GENERATED_TESTS): Renamed gentest to + generated-tests. + + * tests/Makefile.am (OTHER_TESTS, OTHER_FILES): Added manually + maintained tests in tests/other-tests. These currently tests for + 8-bit transparency, multiple precision arithmetic and sync-line + output. Test for stackoverflow detection does not work. + + * examples/Makefile.am (TESTS): Added tests for all example files. + + * examples/mktests.sh: New file. Help program for creating test + files. + + * tests/mkconfig.sh: New file to generate tests/config.m4 and + tests/config.sh. This is for tests of configure selectable + features. Picks up all set WITH_ and ENABLE_ veriables from + config.h + + * src/path.c (path_search): Added argument 'char **expanded_name' + to return the expanded name. + + * src/m4.h: Added 2nd argument to declaration of path_search(). + + * src/m4.c (main): Added 2nd argument to path_search(). + + * src/freeze.c (reload_frozen_state): Do. + + * src/builtin.c (m4_undivert): Do. + (include): Do. + +1998-10-11 René Seindal <rene@seindal.dk> + + * acm4/Makefile.am (ACINCLUDES_M4): Added gmp.m4 and modules.m4 + + * acm4/modules.m4: New file. Defines AM_WITH_MODULES. + + * acm4/gmp.m4: New file. Defines AM_WITH_GMP. + + * configure.in: Introduced AM_WITH_MODULES and AM_WITH_GMP. + + * AUTHORS, ChangeLog: Changed all dates to ISO 8601. + + * intl/: Updated to GNU gettext 0.10.35. + + * doc/m4.texinfo (Format): Documented that format is blind. + + * src/builtin.c (builtin_tab): Builtin format marked as blind. + +1998-10-07 René Seindal <rene@seindal.dk> + + * Prerelease 1.4j. + + * tests/Makefile.am (GENERATED_TESTS): Changed .m4 extension to + .test, as the files are no longer just m4 input. + + * tests/get-them (FILE): Changed .m4 extension to .test. + + * src/m4.h (token_type): New token type TOKEN_SPACE introduced. + Otherwise quoted strings with leading whitespace first in a macro + argument would be eliminated. + + * src/macro.c (expand_token): Handles new token type TOKEN_SPACE. + (expand_argument): Do. + + * src/input.c (next_token): SPACE and NUM/OTHER characters are only + grouped together iff both quote and comment strings are single + character. Otherwise they might include a comment/quote leader. + (next_token): Returns new token type TOKEN_SPACE. + + * src/builtin.c (push_builtin_table): New function to push a + builtin_table on the stack without installing its contents. + (find_builtin_by_name): Added call to push_builtin_table() if + reading frozen files. Otherwise the builtins named in the frozen + files could not be found. + (install_builtin_table): Changed to use push_builtin_table() + +1998-10-04 René Seindal <rene@seindal.dk> + + * Prerelease 1.4i. + + * configure.in (ALL_LINGUAS): Added Polish pl.po + +1998-10-03 René Seindal <rene@seindal.dk> + + * Many files: Incorporated changes to implement dynamic modules. + Detailed comments in src/modules.c and modules/README + + * src/module.c: New file, implements the OS dependant parts of + dynamic module loading. + + * src/Makefile.am (m4_SOURCES): Added module.c + + * src/builtin.h: New file, declares some functions from builtin.c + that are of use for other modules (shipout_int, numeric_arg, + skip_space, bad_argc), and the macros ARG() and DECLARE(). + + * src/builtin.c (install_builtin_table): New function. Each + module brings in a builtin_table, which is pushed on a stack. + (struct builtin_table): New struct for list of builtin_tables. + (m4_loadmodule): New function to implement builtin "loadmodule". + (shipout_int): No longer static, to be used by modules. + (numeric_arg): do. + (skip_space): do. + (bad_argc): do. + (builtin_init): changed to call install_builtin_table() + (find_builtin_by_name): Now searches all builtin_tables + (find_builtin_by_addr): do. + + * src/path.c: Reorganised to allow for two search paths, one for + include files and one for modules. + + * src/m4.h: Added declarations for new functions in module.c and + in path.c. + + * src/m4.c (main): Added call to module_init(). + + * modules: New directory with a few demo modules. + + * Makefile.am (EXTRA_DIST): Added modules/* since modules/ is not + in SUBDIRS. + + * configure.in: Added modules/Makefile to AC_OUTPUT. + + * configure.in: Added code to implement --with-modules. Tests for + <dlfcn.h> and -ldl. + + * acconfig.h: Added WITH_MODULES + +1998-10-02 René Seindal <rene@seindal.dk> + + * examples/Makefile.am (pkgdata_DATA): Removed special target for + check and variables TESTS. These tests are now run from the + tests/ directory. + + * tests/Makefile.am (OTHER_TESTS): Added tests from the example/ + directory. The files stay there but the tests are run from the + tests/ directory. + + * tests/Makefile.am (EXTRA_DIST): Added run-test. + + * tests/run-test: New file. Run a test manually + + * tests/Makefile.am, tests/get_them: Moved automatically generated + tests (from the manual) to sub directory tests/gentest/. The + tests/ directory had gotten a bit messy. + +1998-09-06 Erick Branderhorst <Erick.Branderhorst@asml.nl> + + * examples/{comments,ddivert,debug,iso8859,reverse,sysv-args,\ + wrap}.test: Added a few testcases. + +1998-08-21 Erick Branderhorst <Erick.Branderhorst@asml.nl> + + * Prerelease 1.4h. + + * lib/Makefile.am (noinst_HEADERS): regex.h added + + * configure.in (jm_WITH_REGEX, jm_PREREQ_ERROR): + acm4/{error,regex}.m4 (from fileutils-3.16u.tar.gz). + + * acm4/Makefile.am: created providing rules to create + $(top_srcdir)/acinclude.m4 to be used by aclocal. + + * tests/defs (LANGUAGE, LC_ALL, LANG): force them to be + `C'. Reported by Ulrich Drepper. + + * Makefile.am (SUBDIRS): Removed checks directory + * configure.in (AC_OUTPUT): Removed checks/Makefile + + * doc/m4.texinfo (Patsubst,example): @comment added to preserve + the space when m4.texinfo is edited and whitespace.el is active. + (Defn,example): idem. + +1998-08-20 Erick Branderhorst <Erick.Branderhorst@asml.nl> + + * doc/m4.texinfo (Esyscmd): grep ../Makefile instead of + ../COPYING. ../Makefile is a file which is certainly present when + test is executed in testSubDir. One can't be sure that the COPYING + file is in .. or ../.. in all situations, the ../Makefile is + always there. + + * doc/m4.texinfo (Include): adjusted expected test output + according to new tests, i.e. the input will always come from the + file `in' created by the test. + + * tests/Makefile.am: Added three lines at the top to get + esyscmd.1.test working. + + * tests/get-them: modified to generate clearer tests who will need + less maintenance when new test examples are created in + `doc/m4.texinfo'. All tests are small (nearly stand-alone, they + need the generic file `defs') shell scripts creating `in', `ok', + `out' and when apropriate `okerr' and `err' in the directory + `testSubDir' when executed. The compare of `ok' and `out' + (and of `okerr' and `err') will be the exit status of the test. + `out' must match `ok' (and `okerr' must match `err') for the test + to be succesful. + + * tests/[a-b]\{1,8\}.[0-9]+.test: This namespace is reserved for + the tests generated by tests/get-them getting it input normally + from doc/m4.texinfo. The namespace tests/[a-b]+[0-9]+.test (no `.' + (dot) before the numeric part) is reserved for all other (hand + written) tests. The `+' means one or more times. + +1998-08-12 Erick Branderhorst <Erick.Branderhorst@asml.nl> + + * doc/Makefile.am (EXTRA_DIST): helptoman.pl and $(MANS) to + supported short man page to refer to info documentation + * helptoman.pl: added + * configure.in: AC_PATH_PROG(PERL,perl) + * Makefile.am (SUBDIRS): doc after src + + * libitized with libit 0.5 from + ftp://ftp.iro.umontreal.ca/pub/contrib/pinard/maintenance/libit. + + * configure.in (AC_REPLACE_FUNCS): added xmalloc xstrdup + * lib/Makefile.am (libm4_a_SOURCES): removed automakely supported + replacement functions, (libm4_a_LIBADD): @LIBOBJS@ + * configure.in (AM_WITH_REGEX), acconfig.h (WITH_REGEX): added + lib/rx.{c,h}: added + * configure.in (AC_CHECK_FUNC): getopt_long + + * src/m4.c (usage): Report bugs to m4-bugs@gnu.org. + + * TODO: added entry about dependencies + +1998-08-10 René Seindal <rene@seindal.dk> + + * Prerelease 1.4f + + * doc/m4.texinfo (Changesyntax): Added documentation for the macro + "changesyntax". + + * src/builtin.c (m4_changesyntax): Added builtin macro + "changesyntax" to modify the syntax table. + + * src/input.c, src/m4.h, src/macro.c: Implemented an input syntax + table. All categories are assigned a syntax code and tokens are + read according to this table. + +1998-08-09 René Seindal <rene@seindal.dk> + + * src/numb.{c,h}: New files, implements multiple precision eval + using GNU gmp. Originally submitted by John Gerard Makecki + (johnm@vlibs.com), later modified. Tested with GNU gmp 2.0.2. + + * doc/m4.texinfo (Eval): Added documentation for multiple + precision arithmetic library support. + + * src/m4.{c,h}, src/eval.c, src/builtin.c, configure.in: Changes + to accommodate multiple precision eval. + +1998-08-07 René Seindal <rene@seindal.dk> + + * src/input.c (MATCH, match_input), src/m4.h: changed definition + of comment and quote strings to `unsigned int' to allow eight bit + chars (reported by andrewb@zip.com.au (Andrew Bettison)). + + * src/builtin.c, doc/m4.texinfo: Builtin `syncoutput' added by + patch from Mike Howard <mike@clove.com> + +1998-08-06 René Seindal <rene@seindal.dk> + + * gettext.m4: corrected AM_WITH_NLS to handle use of installed + -lintl. + +1998-08-03 René Seindal <rene@seindal.dk> + + * Prerelease 1.4e + + * src/m4.h: Added ifdef ENABLE_NLS around include of <libintl.h> + and _ macro. M4 now builds with --disable-nls. + + * src/m4.c (main): reintroduced textdomain(PACKAGE) to get gettext + to look for right message catalogs. Call indef'ed by ENABLE_NLS. + + * configure.in (ALL_LINGUAS): Added complete list of translations: + de fr it ja nl ru sv. + +1998-05-22 Erick Branderhorst <Erick.Branderhorst@asml.nl> + + * Prerelease 1.4d. + + * src/m4.c: #include <signal.h> not <sys/signal.h>. + + * src/Makefile.am: CFLAGS = -Wall @CFLAGS@. + + * checks/Makefile.am: explicit list tests in CHECKS. + + * configure.in, {,src,doc,lib,examples,checks}/Makefile.am, + src/{ansi2knr.{1,c}} doc/{m4.texinfo,mdate-sh}, missing, + mkinstalldirs, install-sh: Added automake (1.3) support. + + * lib/{alloca.c,error.{c,h},get{date.h,opt.{c,h},opt1.c}, + obstack.{c,h},regex.{c,h},strtol.c,xmalloc.c,xstrdup.c}: + Used libitize (0.4) to update. + + * configure.in, ABOUT-NLS, intl/*, po/*: Added gettextize + (0.10.25) support. Removed LOCALE, fr.msg, m4.cod and adjusted + README accordingly. + + * src/stackovf.c: #ifdef USE_STACKOVF ... #endif to (de-)activate + stack overflow functionality. + +1994-12-03 François Pinard <pinard@iro.umontreal.ca> + + * Prerelease 1.4.1. + + * Makefile.in (realclean-local): Delete stamp-h.in. + + * configure.in, {,src,lib}/Makefile.in, src/m4.h, src/m4.c: + Localize, adapting from how it is done in sharutils. + + * fr.tt: New file, for French. + + * configure.in, {,*/}Makefile.in, acconfig.h, src/m4.c, + src/freeze.c: Rename PRODUCT to PACKAGE. + +1994-11-26 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Check for <libintl.h> and <locale.h>. + * src/m4.h, src/builtin.c, src/debug.c, src/eval.c, src/macro.c, + src/stackovf.c: Rename _ to __P. + * src/m4.h: Declare _ as a macro returning its argument, or else, + include <libintl.h> and declare _ as gettext. + * src/m4.c: Possibly include <locale.h> and call setlocale. + * src/m4.c, src/builtin.c, src/debug.c, src/eval.c, src/freeze.c, + src/input.c, src/macro.c, src/output.c, src/path.c, + src/stackovf.c, src/symtab.c: Use _ macro over all localizable + strings. + +1994-11-07 François Pinard <pinard@iro.umontreal.ca> + + * doc/Makefile.in (stamp-vti): Use new -r option to date. + + * configure.in: Put --with-gmp in place, in prevision for John + Gerard's work. + * acconfig.h: Document WITH_GMP. + +1994-11-05 François Pinard <pinard@iro.umontreal.ca> + + * Release 1.4. + + * doc/Makefile.in (realclean): Also remove stamp-vti. + Reported by Eric Backus. + +1994-11-02 François Pinard <pinard@iro.umontreal.ca> + + * src/freeze.c (produce_frozen_state): If the frozen file cannot + be opened, return immediately after producing the error message. + Reported by Andreas Schwab. + + * configure.in: Check for const only after having found possible + ANSIfying compiler flags, this is of no use to check it before. + Reported by Alexander Lehmann. + +1994-11-01 François Pinard <pinard@iro.umontreal.ca> + + * src/macro.c (collect_arguments): Cast obstack arguments to + (voidstar), so avoiding compiler warnings. + Reported by Joseph E. Sacco. + + * src/freeze.c (produce_frozen_state): Cast printed lengths to + (int) so they correspond to %d format items. + Reported by Joseph E. Sacco. + + * src/m4.c (main): Cast the argument to xfree to (voidstar). + * src/symtab.c (free_symbol): Idem. + Reported by Karl Vogel. + +1994-10-31 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (DISTFILES): Distribute BACKLOG. + + * configure.in: Define PRODUCT and VERSION. + * acconfig.h: Document PRODUCT and VERSION. + * src/m4.c, src/freeze.c: Use PRODUCT and VERSION instead of the + constant string m4 and variable or parameter named version. + +1994-10-30 François Pinard <pinard@iro.umontreal.ca> + + * src/m4.h, src/debug.c: Replace all #ifdef __STDC__ by #if + __STDC__. Alliant FX/2800 Concentrix 2.2 (i860-BSD4.3) compiler + defines __STDC__ to 0, for indicating it is *not* ANSI! + Reported by Kaveh R. Ghazi. + + * configure.in: Added obsolescent tests for AIX and Minix. + + * doc/Makefile.in (mostlyclean): Remove texclean in dependencies, + which texclean does not exist anymore. + Reported by Eric Backus, Jim Meyering, John David Anglin and + Joseph E. Sacco. + +1994-10-29 François Pinard <pinard@iro.umontreal.ca> + + * aclocal.m4 (fp_C_PROTOTYPES): Force -D_HPUX_SOURCE with -Aa. + Reported by John David Anglin. + + * src/ansi2knr.c: New version, sent by Peter Deutsch. + * aclocal.m4 (fp_C_PROTOTYPES): Substitute empty or ansi2knr for + ANSI2KNR, depending on the fact the compiler is ANSI or not. + * src/Makefile.in: Use -Ovarargs=convert on ansi2knr calls. + Remove the sed filter after ansi2knr for debug.c. Use $O instead + of $U, put underline in extensions rather than in basenames. Use + implicit rules, now that regularity makes this possible. + Have $(OBJECTS) depend on $(ANSI2KNR), so to trigger compilation + of ansi2knr whenever it is needed. + * configure.in: Adjusted for correct STACKOVF substitution. + * src/debug.c (trace_format): When not __STDC__, use (...) as a + parameter list, so ansi2knr will convert it to (va_alist) va_dcl. + Reported by David MacKenzie. + + * Makefile.in: Remove binprefix. Use transform_name instead. + Reported by David MacKenzie. + + * doc/Makefile.in: Create version.texi, use it, clean it. + Reported by Jim Meyering. + +1994-10-28 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (all, install, uninstall): Depend on Makefile. + + * Makefile.in: For actions invoking $(MAKE) from within compound + sh statements, exit non-zero if the sub-make fails. Otherwise, + the top-level make may exit successfully when it should fail. + Reported by Jim Kingdon. + + * {,/*}Makefile.in: Use && after all cd, in case they fail. + + * {,*/}Makefile.in: Declare PRODUCT and VERSION macros. + (dist): Use PRODUCT and VERSION instead of tricks on .fname. + * configure.in: Substitute PRODUCT and VERSION. + + * {,*/}Makefile.in (dist): Always try a hard link before a copy. + +1994-10-27 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (mostlyclean-local): Do not remove *~. + * */Makefile.in (mostlyclean): Idem. + Reported by Robert E. Brown and Richard Stallman. + +1994-10-09 François Pinard <pinard@iro.umontreal.ca> + + * src/m4.h: Get rid of CONFIG_BROKETS. + +1994-10-02 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Use AC_ARG_PROGRAM. + * aclocal.m4 (fp_C_PROTOTYPES): Substitute @kr@ by kr or empty. + Reported by David MacKenzie. + +1994-10-01 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Do not add -O to CFLAGS for GNU C, now that + configure does it automatically. + Reported by Jim Meyering. + +1994-09-23 François Pinard <pinard@iro.umontreal.ca> + + * src/stackovf.c: Declare the handler_t typedef earlier in the + code, use it for stackovf_handler. + (setup_stackovf_trap): Use RETSIGTYPE instead of void while + casting sigsegv_handler. + Reported by Robert Bernstein. + + * src/m4.c (main): Initialize program_name to argv[0] without + basename'ing it. + Reported by Karl Berry. + +1994-09-18 François Pinard <pinard@iro.umontreal.ca> + + * src/Makefile.in (TAGS): Include a ../lib/TAGS reference. + Reported by Karl Berry. + +1994-09-14 François Pinard <pinard@iro.umontreal.ca> + + * lib/Makefile.in (mostlyclean): Added. + (TAGS): Make in $(srcdir). + + * configure.in: Use `choke me' in test, like everywhere! + + * {doc,examples,lib,src}/Makefile.in (check): Deleted, as + unreacheable and useless. + + * doc/Makefile.in (texclean): Deleted, merged in mostlyclean. + + * lib/Makefile.in (DISTFILES): Distribute TAGS. + (distclean): Do not remove TAGS. + (realclean): Remove it. + * Makefile.in: Make TAGS in lib also, not just in src. + Reported by Karl Berry. + + * Makefile.in (distclean, realclean): Instead of recursively + calling $(MAKE) for the -local part, allow parallel execution of + -recursive and -local, only delay the removal of config.status, + which is repeated in both goals. + +1994-09-13 François Pinard <pinard@iro.umontreal.ca> + + * Release 1.3. + + * Makefile.in: Group all *clean-recursive goals in one, using sed + to remove `-recursive' while calling make recursively. Also, use + a subshell for each recursive $(MAKE). + Reported by Jim Meyering. + + * src/m4.h (memcpy): Define with bcopy for BSD systems. + Reported by Kaveh R. Ghazi. + + * src/Makefile.in (ansi2knr): Use $(LIBS) while linking, for SunOS + 4.1.3 requires -ldl to link even ansik2nr, and we need a way to + specify it. + + * configure.in: Use date instead of touch for stamp-h. + * Makefile.in (stamp-h.in): Idem. + + * Makefile.in (distclean, realclean): Force serial execution of + both goals, in case parallel makes are being used. + Reported by Jim Meyering. + + * src/Makefile.in (DISTFILES): Distribute TAGS. + (distclean): Do not remove TAGS. + (realclean): Remove it. + Reported by Karl Berry. + +1994-09-10 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Use fp_ to match aclocal.m4. Revert _OS_ macros + to old names, for following Autoconf. + +1994-09-08 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (MDEFINES): Remove INSTALL substitutions, for + ./install.sh will not be correctly referred to in sub-Makefiles. + Reported by John David Anglin. + + * doc/Makefile.in (texclean): Remove *.cps and *.fns too. + Reported by Eric Backus. + + * Makefile.in, checks/Makefile.in, doc/Makefile.in, + examples/Makefile.in, lib/Makefile.in, src/Makefile.in: Limit + config.status into remaking this directory's Makefile only. + * Makefile.in (stamp-h): Do not check nor touch stamp-h. + * configure.in (AC_OUTPUT): Touch stamp-h if CONFIG_HEADERS. + Reported by Jim Meyering. + +1994-09-06 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Correct stack overflow detection logic, taking + care of systems having only incomplete implementations (like for + Pyramid 9820 OSx 5.0d). + Reported by Kaveh R. Ghazi. + + * src/Makefile.in (TAGS): Remote -t from etags call. + +1994-09-02 François Pinard <pinard@iro.umontreal.ca> + + * lib/Makefile.in (install): Depend on all. + +1994-08-31 François Pinard <pinard@iro.umontreal.ca> + + * examples/Makefile.in (mostlyclean): Do not depend on texclean. + Reported by Jim Meyering and John David Anglin. + + * Makefile.in (distclean-local): Delete config.log. + Reported by Jim Meyering. + + Solidify frozen files with respect to -P: + * src/m4.c: Have -P set prefix_all_buitins variable instead of + calling a function by that name. Declare the variable. + * src/m4.h: Adjust declaration for prefix_all_buitins. + * src/builtin.c (builtin_init): Merge in functionality from + previous prefix_all_buitins function, while making entries in the + symbol table, but not modifying the builtin description itself. + + * src/freeze.c (reload_frozen_state): Add a useless `break;', + because *many* compilers do not accept an empty `default:'. + Reported by Akiko Matsushita, Eric Backus, John David Anglin, + Joseph E. Sacco, Kaveh R. Ghazi, Tom McConnell and Ulrich Drepper. + + * configure.in: Use AC_TYPE_SIGNAL. + * src/stackovf.c (setup_stackovf_trap): Use RETSIGTYPE. + Reported by Robert Bernstein. + + * checks/Makefile.in (check): Modify PATH so check-them will find + m4 in the src directory. + * Makefile.in (check): Don't. + Reported by Akiko Matsushita and Jim Meyering. + + * src/output.c (make_room_for, output_character_helper): New + functions, for implementing a global MAXIMUM_TOTAL_SIZE instead of + a per buffer MAXIMUM_BUFFER_SIZE. + + * src/output.c (output_text): New function, for optimizing the + output of strings of characters. Use it. + +1994-08-30 François Pinard <pinard@iro.umontreal.ca> + + * doc, src: New directories reorganizing the distribution. + * doc/Makefile.in, src/Makefile.in, examples/Makefile.in: New + files. + * Makefile.in: Adjusted. + * configure.in: Configure new Makefiles. + + * m4.h: Declare STRING typedef. Use it for comment and quote + strings, adjusting all references. (This is the rudiments of a + beginning for the eventual withdrawal of NUL terminated strings.) + * output.c (shipout_text): Accept a length parameter, and use it. + All callers adjusted. + +1994-08-29 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Include <unistd.h> if it exists. + * stackovf.c: Don't. + + Clean up for current_diversion variable: + * output.c: Move current_diversion from builtin.c. + * m4.h: Declare current_diversion so builtin.c can access it. + * output.c (output_init, make_diversion): Initialize or update + current_diversion. + * builtin.c (builtin_init, m4_divert): Leave current_diversion + alone. + + Remove limit on number of diversions: + * output.c: Replace ndiversion by diversions, declare it. + (output_init): Allocate only diversion 0. + (make_diversion): Allocate new diversions as needed. + * m4.h, m4.c: Remove NDIVERSIONS and ndiversion related stuff. + * m4.c: Still accept -N, but do nothing with it. + Reported by David MacKenzie. + + Freeze diversions: + * output.c (freeze_diversions): New function. + * m4.h: Declare freeze_diversions. + * freeze.c: Document frozen file format, revise it, call + freeze_diversions to add diversions to frozen format, and code to + reload them properly. + * m4.c: Do not undivert automatically at end when status being + frozen. Do not call builtin_init when reloading frozen state. + + Speed up diversion processing: + * output.c: Add INITIAL_BUFFER_SIZE, MAXIMUM_BUFFER_SIZE, + COPY_BUFFER_SIZE, in-memory diversion buffers, struct diversion + structure and variables, cached variables out of output_diversion, + reallocate_diversion_for and OUTPUT_CHARACTER. + (shipout_text, make_diversion, insert_diversion): Adapted to new + structures. + (insert_file): Use better buffering. + Reported by David MacKenzie. + +1994-08-28 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in, lib/Makefile.in, checks/Makefile.in: Arrange so + dist works from another build directory. + +1994-08-27 François Pinard <pinard@iro.umontreal.ca> + + * symtab.c (hack_all_symbols): Use hash_table_size instead of + constant HASHMAX, for -H option to work better. + + * builtin.c (DECLARE): Simplify by using _ (). + + * freeze.c: New file. + * Makefile.in: Compile it, distribute it. + * m4.c: Recognize, document and process --freeze-state (-F) and + --reload-state (-R) options. Pass a true flag to builtin_init + only if no reloading some state. + * builtin.c (define_builtin): Remove static specifier. + (find_builtin_by_name): Remove static specifier. + (builtin_init): Accept and obey a flag argument. + * m4.h: Add declarations for freeze.c, changes for builtin.c. + +1994-08-24 François Pinard <pinard@iro.umontreal.ca> + + * builtin.c (dumpdef_cmp): Rewrite so the cast protect the const + specifier. + + * configure.in: Implement --with-dmalloc. + * acconfig.h: Document WITH_DMALLOC. + * m4.h: Add code for when WITH_DMALLOC. + +1994-08-15 François Pinard <pinard@iro.umontreal.ca> + + * m4.c (long_options): Use "error-output", the dash was missing. + Reported by Akiko Matsushita. + +1994-08-12 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Include <sys/types.h>. + * builtin.c, debug.c, m4.c, output.c, stackovf.c: Don't. + * m4.h: Declare len_lquote and len_rquote as size_t, not int. + int. + * input.c: Declare len_lquote, len_rquote, len_bcomm and len_ecomm + as size_t, not int. + * builtin.c (dump_args): Declare len as size_t, not int. + + * debug.c: Prototype the forward declaration of debug_set_file. + + * builtin.c (m4_undivert): Replace div by file, for avoiding the + shadowing of this variable. + * output.c (insert_diversion): Idem. + + * input.c: Delete def_rquote, def_lquote, def_bcomm and def_ecomm. + (input_init): Duplicate default quote and comment strings. + (set_quotes): Free previous quote strings in all cases. Duplicate + even default quote strings. + (set_comment): Free previous comment strings in all cases. + Duplicate even default comment strings. + + * configure.in: Updated for Autoconf 2.0. + * Makefile.in (distclean-local): Also delete config.cache. + + * m4.c (usage): Reorganize the --help output by topic. Include a + description for debugging flags. + +1994-07-29 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: If sigaction is available and SA_ONSTACK defined, + use sigaction. Otherwise, if sigvec is available and SV_ONSTACK + defined, use sigvec. Else don't compile stackovf.c. + * stackovf.c (setup_stackovf_trap): Idem. + Reported by Jim Avera, Karl Berry, Kaveh R. Ghazi, Matthias Rabe + and Simon Leinen. + +1994-07-21 François Pinard <pinard@iro.umontreal.ca> + + * m4.c (usage): Replace printf par fputs. + +1994-07-18 François Pinard <pinard@iro.umontreal.ca> + + * Release 1.2 + +1994-07-17 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Check for sigaction and sigvec. Add a new delayed + check for RLIMIT_STACK, combine in the checking for getrlimit. + All those things are not universally available. + * stackovf.c: Split setting up the trap handler and catching + signals, for better taking care of various configure outcomes. + * examples/stackovf.sh: Correct a typo. + Reported by Eric Backus, Jim Avera and Jim Meyering. + +1994-07-16 François Pinard <pinard@iro.umontreal.ca> + + * ansi2knr.c: New version sent by its author, Peter Deutsch. + +1994-07-15 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in: Modify so parallel make will not try making + lib/libm4.a twice simultaneously. + Reported by Jim Meyering. + +1994-07-14 François Pinard <pinard@iro.umontreal.ca> + + * stackovf.c (setup_stackovf_trap): Replace "Don't" by "Do not" in + error message, for when no code possibility exists. Even if this + line is completely #ifdef'ed out, it brings a syntax error. + Reported by Andreas Schwab, Jim Meyering and Joseph E. Sacco. + + * Makefile.in (install): Have install depend on all too, for lib + to be remade as needed. + + * examples/stackovf.sh: Try ksh, bsh and bash for shells + providing ulimit, instead of using only ksh. + Reported by Jim Avera and Joseph E. Sacco. + +1994-07-12 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (check): Have it depend on all instead of m4. In + this way, a change in lib will be detected and processed. + + * builtin.c (numeric_arg): Use strtol and verify the conversion, + instead of using sscanf which stops as soon as there is a + non-digit in the input. Previously, incr(1xyzzy), eval(1,2xyzzy) + and divert(1xyzzy) were all accepted without any warning or error + messages. + * m4.h: Declare strtol as long if not including stdlib.h. + * configure.in: Check for limits.h, and replace strtol if missing. + * lib/Makefile.in: Substitute LIBOBJS. Distribute strtol.c. + * lib/strtol.c: New file, from elsewhere. + Reported by Andreas Schwab. + +1994-07-07 François Pinard <pinard@iro.umontreal.ca> + + * macro.c (expand_macro): Cast value to (boolean) prior to + assigning it to traced. + Reported by Tom McConnell. + + * Makefile.in (m4): Always make all in lib first. + Reported by Jim Meyering. + +1994-07-06 Jim Avera <jima@netcom.com> + + * stackovf.c: Isolated OS-dependent sections; Improved portability, + adding support for SunOS/BSD (sigvec, sigstack, and 4-parameter signal + handlers), and a default error message if the fault address is not + available (when neither siginfo.h nor BSD sigcontext are supported). + * configure.in: Changes for stackovf.h: Check for sigcontext, + sigaction, sigstack, and define rlim_t as int if necessary. + * acconfig.h: Added HAVE_SIGCONTEXT and rlim_t. + * examples/stackovf.sh: Run m4 -L99999999 to allow stack overflow. + * ansi2knr.c: Fix for func-ptr args; convert "..." to varargs syntax. + +1994-07-05 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Use AC_SET_MAKE. + * Makefile.in: Use @SET_MAKE@. + Reported by Jim Meyering. + + * checks/check-them: Do not trap on SIGQUIT or SIGALRM. + Reported by Ian Taylor. + +1994-07-02 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Remove dependency of USE_STACKOVF on STDC_HEADERS, + because siginfo.h is unrelated to standard headers, and siginfo.h + is already checked for. + Reported by Joseph E. Sacco. + + * acconfig.h, aclocal.m4, m4.h: Replace HAVE_PROTOTYPES by + PROTOTYPES. + * aclocal.m4, configure.in: Replace AC_HAVE_PROTOTYPES by + AC_PROTOTYPES. + +1994-06-29 François Pinard <pinard@iro.umontreal.ca> + + * builtin.c (substitute): Use \& to represent this part of the + string which was matched by the whole regexp, instead of + representing the whole string. Any usage of \0 issues a warning + and acts like \&, it will disappear in some subsequent release. + +1994-06-27 François Pinard <pinard@iro.umontreal.ca> + + * m4.c: Complete prototype for forwarded declaration of usage. + + * input.c (init_macro_token): Correct own reference in error + message. Previous name get_macro_func was referred to instead. + (next_char): Correct own reference in error message. Previous + name advance_input was referred to instead. + + * m4.h: Declare eval_t and unsigned_eval_t typedefs to 32 bits. + * eval.c (logical_or_term, logical_and_term, or_term, xor_term, + and_term, not_term, logical_not_term, cmp_term, shift_term, + add_term, mult_term, exp_term, unary_term, simple_term): Add + prototype to forwarded declarations. Declare parameter v1 as + eval_t * instead of int *. Same for local variable v2 in dyadic + functions. Same for result in exp_term. + * builtin.c (m4_eval): Declare value as eval_t instead of int. + (ntoa): Declare value as eval_t instead of int. Declare uvalue as + unsigned_eval_t instead of unsigned int. Change casts accordingly. + (shipout_int): Cast first argument of ntoa to eval_t. + Reported by Thorsten Ohl. + + * macro.c: Complete the prototypes of forwarded expand_macro and + expand_token. + Reported by Thorsten Ohl. + + * m4.h: Define voidstar as void * or char * depending on __STDC__. + The Ultrix 3.1 compiler cannot do much with void pointers. + + * builtin.c (dumpdef_cmp): Replace void * by voidstar. + * m4.c (xfree): Replace void * by voidstar. + Reported by Tom McConnell. + + * ansi2knr.1: New, from elsewhere. + * Makefile.in (DISTFILES): Distribute ansi2knr.1 + + * Makefile.in (stamp-h.in): Avoid running ./config.status if + stamp-h does not exist yet. This avoids running it a second time + just after the initial ./configure. + Reported by David MacKenzie and Tom McConnell. + + * m4.h: Replace the enum debug_info declaration with a series of + #define's. The Ultrix 3.1 compiler would otherwise need casting + (int) to most references, when used in expressions. + Reported by Tom McConnell. + +1994-06-25 François Pinard <pinard@iro.umontreal.ca> + + * aclocal.m4: Replace FP_PROTOTYPES by AC_HAVE_PROTOTYPES, + following an idea from Brook G. Milligan. AC_HAVE_PROTOTYPES + calls the compiler. Previously, FP_PROTOTYPES was only calling + the preprocessor; by not being subject to CFLAGS, this was + discouraging those flags asking for ANSI compilation. + * acconfig.h: Document HAVE_PROTOTYPES. + * configure.in: Use AC_HAVE_PROTOTYPES instead of FP_PROTOTYPES. + * m4.h: Define _() according to HAVE_PROTOTYPES, not __STDC__. + Reported by Eric Backus. + + * configure.in: Substitute CFLAGS and LDFLAGS, taking their value + from the environment. Default CFLAGS to -g if not set. + * Makefile.in: Have CFLAGS and LDFLAGS substituted from configure. + * lib/Makefile.in: Have CFLAGS substituted from configure. + Reported by Eric Backus and Tom McConnell. + + * configure.in: m4_undefine changeword before using AC_ENABLE. + + * m4.h: Declare prototypes for error (for ANSI compilers only), + prefix_all_builtins and reference_error. + Reported by Tom McConnell. + + * input.c (set_word_regexp): Do not try to initialize the array + test from a string, this does not work with non-ANSI compilers. + Reported by Eric Backus. + + * Makefile.in (dist): Clean examples/ before saving it. + (distclean-local): Also remove stamp-h. + Reported by Eric Backus. + + * Makefile.in (_stackovf.c): Goal for compiling stacokovf.c with + non ANSI compilers. + Reported by Tom McConnell. + + * checks/Makefile.in (clean): Depends on mostlyclean. + (mostlyclean): New goal. + +1994-06-24 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (DISTFILES): Distribute install.sh. + * install.sh: New file, copied from elsewhere. + Reported by Assar Westerlund and Kaveh R. Ghazi. + +1994-06-23 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Define ENABLE_CHANGEWORD if --enable-changeword. + * acconfig.h: Explain ENABLE_CHANGEWORD. + + [These modifs all depend upon ENABLE_CHANGEWORD and are adapted + from code provided by Pete Chown] + * m4.h: Add original_text field to u_t variant of union u. + Declare TOKEN_DATA_FUNC macro. + * builtin.c: Declare changeword. + (m4_changeword): New function. + * input.c: Include "regex.h", define variables with word regexps. + (input_init): Initialize the word regexp. + (set_word_regexp): New. + (next_token): Declare local variables, use the previous code if + default_word_regexp is true. Else, match using a new code. Save + the original text. + * macro.c (expand_token): Ship out original text if not a macro + name. + Reported by Krste Asanovic and Pete Chown. + + [These modifs all depend upon ENABLE_CHANGEWORD] + * m4.h: Declare external user_word_regexp. + * m4.c: Declare user_word_regexp, and initialize it from + --word-regexp or -W, or NULL if not specified. + * input.c: Use user_word_regexp if specified, instead of + DEFAULT_WORD_REGEXP. + + * Makefile.in (m4): Revert Jan 3 1994 change. I'm unable to + agree with it. + + * Makefile.in, lib/Makefile.in: Limit suffixes to .c and .o. + * checks/Makefile.in: Empty the suffix list. + Reported by Geoff Russell, Joel Sherrill and Roland McGrath. + + * m4.c: Declare nesting_limit and initialize it to 250. + Implement -LNUMBER or --nesting-limit=NUMBER to change its + value. + * m4.h: Declare nesting_limit as external. + * macro.c (expand_macro): Stop execution whenever nesting limit + is exceeded. + Reported by Bengt Mertensson. + + * eval.c (evaluate): Diagnose excess characters in eval input. + Things like `eval(08)' used to return 0 with no diagnostic. + + * m4.h: Capitalize first letter of all macro arguments in + definitions. + + * m4.c: Declare warning_status, initialize it to 0. Add new + option -E, or --fatal-warnings, which sets warning_status to + EXIT_FAILURE instead. + * m4.h: Declare external warning_status. Define EXIT_SUCCESS and + EXIT_FAILURE if not otherwise done by header files. + * m4.c: Delete declarations for EXIT_SUCCESS and EXIT_FAILURE. + * m4.c, input.c, output.c, symtab.c, builtin.c, macro.c, debug.c, + eval.c: Replace 0 by warning_status and 1 by EXIT_FAILURE in first + argument of all M4ERROR calls. + Reported by Noah Friedman. + + * examples/incl-test.m4: Renamed from incl_test.m4. + * examples/include.m4: Include incl-test.m4 instead of + incl_test.m4. + * examples/multiquotes.m4: Renamed from multi-quotes.m. + +1994-06-22 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Avoid USE_STACKOVF if <siginfo.h> not found. Note + that Jim developped stackovf.c on a 486 running SVR4.0 (ESIX), and + also tested it on a Sun Sparc workstation running SunOS 4.x. + + * format.c (format): When not HAVE_EFGCVT, m4 was failing the + 49.format check, abusing a `union values' argument with sprintf + without selecting the proper field. Now, save the formatting type + first, delaying the fetch of the corresponding argument. + Reported by Joseph E. Sacco and Tom Quinn. + + * format.c (format): Remove const from char *fmt declaration when + not HAVE_EFGCVT, because a NUL may be forced into it. + + * m4.h: Declare atof() when not STDC_HEADERS. + Reported by Joseph E. Sacco. + + * Regenerate configure using Autoconf 1.11, this corrects a + problem about an incorrect cpp seting on NeXT 3.1. + Reported by Alexander Lehmann. + +1994-06-05 François Pinard <pinard@iro.umontreal.ca> + + * m4.h (_): Change argument from `x' to `Args'. + +1994-04-22 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Rename Args() to _(). + * m4.h: Remove extern specifier from all function declarations. + +1994-04-22 Jim Avera <jima@netcom.com> + + * stackovf.c: New file implementing stack-overflow detection. + * configure.in: Check for getrlimit, sigaction. If all of + standard headers, getrlimit and sigaction, define USE_STACKOVF and + substitute ${U}stackovf.o for STACKOVF. + * acconfig.h: Declare USE_STACKOVF. + * Makefile.in: Distribute stackovf.c, link with $(STACKOVF). + * m4.h: Declare setup_stackovf_trap(). + * m4.c: Call setup_stackovf_trap(). + * tests/stackovf_test.sh: New file. + +1994-04-13 François Pinard <pinard@iro.umontreal.ca> + + * checks/Makefile.in: Rename .all-stamp to stamp-checks. + + * Makefile.in (Makefile, etc.): Adapt for Autoconf 1.8. + +1994-01-30 <pinard@iro.umontreal.ca> + + * m4.h: Remove definition of volatile, not used anymore. + Reported by Jim Meyering and Joseph E. Sacco. + + * m4.h: Consistently use `do { ... } while (0)' in macros, instead + of `if ... else /* nothing */' for if macros. + Reported by Jim Meyering. + + * builtin.c (m4_regexp): Reorganize the code for avoiding a + warning from gcc about `repl' possibly used before defined. + Reported by Jim Meyering. + + * m4.h: Avoid a pre-ANSI <memory.h> together with <string.h>. + Reported by Jim Meyering. + +1994-01-25 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Move the conditional definition of volatile after the + inclusion of system files, because they may define it first. + +1994-01-04 François Pinard <pinard@iro.umontreal.ca> + + * checks/Makefile.in (CHECKS): Add a useless `*' before `[', to + get around a problem with Alpha make seeing a syntax error, there. + Reported by Vern Paxson. + +1994-01-03 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in: Do not define LDFLAGS, use CFLAGS on link calls. + Reported by Richard Stallman. + +1993-12-25 François Pinard <pinard@iro.umontreal.ca> + + * configure.in: Correct test for strerror, AC_FUNC_CHECK was used + instead of AC_HAVE_FUNCS. + Reported by Noah Friedman. + +1993-12-01 François Pinard <pinard@iro.umontreal.ca> + + * m4.c: Initialize show_help and show_version to zero. + + * m4.c: Ensure EXIT_SUCCESS and EXIT_FAILURE are defined. + Use them in exit() and usage() calls. + +1993-11-27 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Delete extern sys_nerr, sys_errlist declarations, and + syserr() macro. Delete errref, add reference_error and M4ERROR. + * m4.c: Replace errref, which was returning an input reference + string, with reference_error, which prints it on standard error. + * builtin.c, output.c: Use errno as second parameter to error, + instead of using syserr() with %s. + * *.c: Use M4ERROR instead of error: no more errref() with %s. + Doing so, the program name appears after the input reference + instead of before, which eases M-x next-error processing. + +1993-11-24 François Pinard <pinard@iro.umontreal.ca> + + * checks/get-them: Escape braces with backslashes in patterns, + because HPUX-9.01 awk needs this. + Reported by Jim Meyering. + +1993-11-22 François Pinard <pinard@iro.umontreal.ca> + + * builtin.c: Declare "FILE *popen ();". + + * m4.h: Remove MESSAGE{,1,2}, WARNING1, FATAL{,1}, INTERNAL_ERROR + macros, replace error_message_prefix() declaration by errref()'s. + Declare xrealloc, for use in errref(). + * m4.c: Delete error_message_prefix() function, add errref(). + * *.c: Use error() systematically in place of all error macros, + now that error() flushes stdout first. Make needed adjustments. + + * m4.h: Remove const in sys_errlist[] declaration, it creates + conflicts on SGI and Alpha. + Reported by Kaveh R. Ghazi. + +1993-11-20 François Pinard <pinard@iro.umontreal.ca> + + * m4.c: Include <getopt.h> instead of "getopt.h". + + * configure.in: Output to config.h. Use HAVE_FUNCS preferably. + * acconfig.h: New, for documenting HAVE_EFGCVT. + * Makefile.in: Distribute acconfig.h, .stamp-h.in and config.h.in, + use them wherever appropriate. Also use -I. for compilations. + * lib/Makefile.in: Use -I.. for compilations. + * *.c: Include <config.h> or "config.h". + + * m4.h: Test for HAVE_MEMORY_H instead of NEED_MEMORY_H. + * configure.in: Use AC_HAVE_HEADERS(memory.h), delete AC_MEMORY_H. + +1993-11-17 François Pinard <pinard@iro.umontreal.ca> + + * builtin.c (m4_eval): Cast strlen to (int) before comparing. + + * input.c (input_init): Initialize quote and comment strings + explicitely instead of calling set_quotes and set_comment: by + doing so, we ensure we do not free uninitialized variables. + + * checks/check-them: Reverse arguments to both diff, so the + expected is on the left and the obtained on the right. + + * m4.h: Add MESSAGE{,1,2}, WARNING1, FATAL{,1} and INTERNAL_ERROR + macros. Delete declarations for m4error, warning, fatal and + internal_error, add declaration for error_message_prefix. + * m4.c: Delete m4error, warning, fatal and internal_error + routines, add error_message_prefix routine. + * *.c: Replace m4error routine calls with MESSAGE* macro calls, + warning with WARNING*, fatal with FATAL* and internal_error with + INTERNAL_ERROR*. + * Makefile.in (_m4.c): Do not adjust ansi2knr output for va_alist, + this is not needed anymore. + + * m4.h: Declare extern FILE *debug. Add DEBUG_PRINT{1,3} and + DEBUG_MESSAGE{,1,2} macros. Delete declarations for debug_print + and debug_message, add declaration for debug_message_prefix. + * debug.c: Remove static specifier for FILE *debug declaration. + Delete debug_print and debug_message routines, add + debug_message_prefix routine. + * builtin.c, debug.c: Replace debug_print routine calls with + DEBUG_PRINT* macro calls. + * input.c, path.c: Replace debug_message routine calls with + DEBUG_MESSAGE* macro calls. + + * m4.h: Remove inclusion of <varargs.h>. + * debug.c: Include <stdarg.h> or <varargs.h>. + (trace_format): Use stdarg instead of varargs if __STDC__. + + * configure.in: Remove checks for vfprintf and _doprnt. These + implementations use varargs tricks which are not portable enough. + * lib/vfprintf.c: Deleted. + * lib/_doprnt.c: Deleted. + * lib/Makefile.in: Adjusted accordingly. Remove LIBOBJS. + Reported by Joel Sherrill. + + * path.c (add_include_directory): Use xstrdup. + + * builtin.c (find_builtin_by_name): Declare static. + + * *.[ch]: Add const to a few "char *" declarations. + + * configure.in: Remove commented tests for fileno() and fstat(). + * debug.c: Remove comments about HAVE_FILENO and HAVE_FSTAT. + + * debug.c (debug_flush_files): New. + * m4.h: Declares it. + * builtin.c (m4_syscmd, m4_esyscmd): Use it. + Reported by Nicolas Pioch. + +1993-11-12 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (m4.dvi): Use m4.texinfo instead of m4.texi. + Reported by Joel Sherrill. + + * builtin.c (prefix_all_builtins): Instead of the table size, use + the null entry at end for stopping the loop. It was overwritten. + Reported by Andreas Schwab and Jim Meyering. + + * builtin.c (prefix_all_builtins): Cast xmalloc to (char *). + Reported by Kaveh R. Ghazi. + + * macro.c (call_macro): Add * in (*SYMBOL_FUNC (sym)) (...). + Reported by Karl Vogel. + +1993-11-09 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Do not define volatile if already defined. + Reported by René Seindal. + + * lib/Makefile.in: Add a forgotten ALLOCA=@ALLOCA@. Grrr! + + Reported by Bernhard Daeubler, Eric Backus, Hal Peterson, Hoang + Uong, Ian Taylor, Kaveh R. Ghazi, Tom McConnell and Walter Wong. + +1993-11-08 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Define strchr and strrchr in terms of index and rindex, + instead of the other way around. + * builtin.c, m4.c, path.c: Use strchr instead of index. + + * input.c (next_char): Remove a "break;" after a "return ...;". + Reported by Tom McConnell. + +1993-11-08 François Pinard <pinard@iro.umontreal.ca> + + * Release 1.1 + + * configure.in: Do not copy check files in the build hierarchy. + * checks/check-them: Identify the m4 version being checked. For + finding m4, look in $PATH instead of in the parent directory. + * Makefile.in (check): Prepend `pwd` to $PATH before checking. + * checks/Makefile.in (.all-stamp): Always create check files in + the source hierarchy, not anymore in the build hierarchy. + (check): cd to the source hierarchy before performing checks. + Do not copy nor clean COPYING anymore, take it from `..'. + Reported by Tom McConnell. + + * Makefile.in (Makefile): Use $(SHELL). + (config.status): Use $(SHELL). Use "config.status --recheck" + instead of "configure --no-create", which is obsolete. + Reported by Tom McConnell. + +1993-11-05 François Pinard <pinard@iro.umontreal.ca> + + * m4.c (usage): Use "%s" instead of "m4" in format string. + Reported by Jim Meyering. + + * Makefile.in: Distribute mkinstalldirs. + Reported by Pierre Gaumond. + Reported by Jim Meyering. + Reported by Tom McConnell. + Reported by Andreas Gustafsson. + + * checks/check-them: Renamed from checks/check_them. + * checks/get-them: Renamed from checks/get_them. + * checks/.all-stamp: Renamed from checks/.all_stamp. + * checks/Makefile.in: Changed accordingly. + Reported by Jim Meyering. + +1993-11-04 François Pinard <pinard@iro.umontreal.ca> + + * lib/Makefile.in (dist): Correct permissions on files. + + * output.c: Declare tmpfile, some systems don't. + +1993-11-03 François Pinard <pinard@iro.umontreal.ca> + + * checks/Makefile.in (dist): Correct permissions on files. + + * Makefile.in (dist): Ensure recursive linking for subdirectory + `examples', also set read/write permissions on all its files. + + * mkinstalldirs: New, from elsewhere. + * Makefile.in: Use it. + + * debug.c: Synchronize debug messages and regular output when + the debug file and stdout are redirected to the same file. + * configure.in: Add (commented) checks for fileno and fstat. + Reported by Jim Avera. + + * builtin.c (m4_ifelse): Diagnose excess arguments if 5, 8, 11, + etc., arguments, then ignore the superfluous one. m4 used to + diagnose missing arguments and return the empty string. + Reported by Nick S. Kanakakorn. + +1993-11-02 François Pinard <pinard@iro.umontreal.ca> + + * m4.c (main): At end of all input, ensure all undiverted text + goes to the main output stream. + Reported by Andreas Gustafsson. + + * m4.c (main): exit (0), instead of return 0. + + * m4.c: Implement -P and --prefix-builtins. + * builtin.c: Delete const specifier on builtin_tab. + (prefix_all_builtins): New. + Reported by Noah Friedman. + Reported by Scott Bartram. + + * c-boxes.el: New, from elsewhere. + * Makefile.in: Distribute it. + + * m4.h: Do not define bcopy if <string.h> defines it. + Reported by Stephen Perkins. + + * builtin.c (define_macro): Allow a missing second argument, in + which case it is implied empty. Affects define and pushdef. + Reported by Eric Allman. + +1993-11-01 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Add blind_if_no_args in struct builtin, blind_no_args in + struct symbol adn SYMBOL_BLIND_NO_ARGS macro. + * builtin.c: Initialize all the blindness fields in builtin_tab. + (define_builtin): Copy the blindness of a builtin into its symbol. + * macro.c (expand_token): Avoid processing a blind builtin if the + next character is not an opening parenthesis. + Reported by David MacKenzie. + Reported by Noah Friedman. + + * configure.in: Ensure an exit status of 0 on completion. + Reported by Vivek P. Singhal. + + * eval.c (eval_lex): Admit both lower and upper case letters for + bases greater than 10. Only lower case letters were accepted. + + * eval.c (eval_lex): Recognize 0bDIGITS and 0rRADIX:DIGITS syntax. + Reported by Krste Asanovic. + + * eval.c: Rename NOT to LNOT. Add XOR, NOT, LSHIFT and RSHIFT. + * eval.c (logical_not_term): New name for not_term. + * eval.c (xor_term): New, between or_term and and_term. + * eval.c (not_term): New, between and_term and logical_not_term. + * eval.c (shift_term): New, between cmp_term and add_term. + Reported by Krste Asanovic: ~, ^, <<, >>. + Reported by Ben A. Mesander: ** vs ^. + + * m4.c: Delete xmalloc.c, xrealloc.c, xstrdup.c. + * m4.h: Delete xrealloc.c. + * lib/xmalloc.c: New, from elsewhere. + * lib/xstrdup.c: New, from elsewhere. + * lib/Makefile.in: Distribute and compile them. + + * m4.c: Change progname to program_name. + * builtin.c, eval.c, m4.c, m4.h: Rename error to m4error. + * lib/error.c: New, from elsewhere. + * lib/Makefile.in: Distribute and compile error.c. + * configure.in: Check AC_VPRINTF and for strerror. + * m4.c: Delete cmd_error. Use error instead. + * m4.c: Change label capitalisation to "ERROR", "Warning", etc. + + * m4.h: Delete #define const, let Autoconf takes care of this. + + * m4.c: Remove all code conditionalized by IMPLEMENT_M4OPTS. + Merge parse_args into main. Declare argv to be `char *const *', + then remove superfluous casts. + + * m4.c: Rename --no-gnu-extensions to --traditional. + Reported by Ben A. Mesander. + + * m4.c (usage): Add a status parameter. Supply one in various + calls. Add --help processing. Remove -V for --version. + + * lib/Makefile.in: Put $(CFLAGS) last in .c.o rule. + + * lib/Makefile.in: Have an AR=ar declaration. + Reported by Eric Backus. + Reported by Bjorn R. Bjornsson. + Reported by Tom Tromey. + Reported by Kristine Lund. + Reported by Marion Hakanson. + +1993-10-30 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (m4.info): Use -I$(srcdir) on $(MAKEINFO). + Reported by Noah Friedman. + +1993-10-25 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in: Remove MDEFINES and cleanup. + +1993-06-09 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (dist): Replace "echo `pwd`" by a mere "pwd". + Create a gzip file. + +1993-02-06 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in, lib/Makefile.in, check/Makefile.in: In dist goals, + ensure 777 mode for directories, so older tar's will restore file + modes properly. + +1993-01-17 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in, lib/Makefile.in: Put $(CFLAGS) after $(CPPFLAGS), + so the installer can override automatically configured choices. + Reported by Karl Berry. + +1993-01-15 François Pinard <pinard@iro.umontreal.ca> + + * lib/vfprintf.c: Stolen from Oleo distribution and adapted. The + previous version was not working properly on m68k-hp-bsd4.3. + Reported by Roland McGrath. + + * lib/_doprnt.c: Stolen from Oleo distribution. + * configure.in: Check for _doprnt.c if vfprintf.c selected. + * lib/Makefile.in: Distribute _doprnt.c. + Do not distribute regex.[ch].old anymore. + +1993-01-01 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in, lib/Makefile.in: Reinstate $(CPPFLAGS), use it. + Richard wants it there. + +1992-12-27 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in: Add DEFS to MDEFINES. + * lib/Makefile.in (.c.o): Remove $(CPPFLAGS). + (libm4.a): Remove the library before creating it. + (distclean): Remove tags and TAGS too. + +1992-12-23 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (dvi, m4.dvi): New goals. + + * builtin.c, eval.c, format.c, input.c, m4.[ch], m4.texinfo, + macro.c, output.c, path.c, symtab.c: Change Copyright from + 1989-1992 to the explicit enumeration 1989, 1990, 1991, 1992. + + * examples/divert.m4: Deleted, this bug has been corrected. + + * Makefile.in (texclean, mostlyclean): New goals. + + * Makefile.in (clean): Remove clutter from ansi2knr. + Reported by Pierre Gaumond. + +1992-12-20 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in: Remove $(CPPFLAGS) from the .c.o rule. The user + might well use CFLAGS is s/he needs it. + + * Makefile.in: Allow installation of info files from a separate + build directory. + Reported by Jason Merrill. + Reported by David MacKenzie. + Reported by Skip Montanaro. + Reported by Erez Zadok. + Reported by Assar Westerlund. + +1992-12-19 François Pinard <pinard@iro.umontreal.ca> + + * Release 1.0.3 + This is still a beta release for the future GNU m4 version 1.1. + + * lib/alloca.c: New, from elsewhere. + * lib/Makefile.in: Distribute it. Define and use $(ALLOCA). + + * m4.h: Do not define index/rindex if already defined. If + FALSE/TRUE are already defined, do not redefine them, but merely + define boolean typedef to int. + + * Makefile.in: Use $(DEFS) while compiling ansi2knr. + * ansi2knr.c: Rewrite #ifdef HAVE_STRING_H || STDC_HEADERS, + because some C compilers do not like connectives with #ifdef. + * m4.h: Define `volatile' only if __GNUC__, instead of once for + __GNUC__ and once for __STDC__. + * lib/regex.h: Leave const alone, AC_CONST will take care of it. + + * checks/Makefile.in: Use .all_stamp instead of $(CHECKS) for + Makefile dependencies. Without it, make keeps destroying and + remaking $(CHECKS) in a loop (why?). Distribute .all_stamp. + + * m4.h, m4.c, builtin.c, output.c: Change all divertion/DIVERTION + to diversion/DIVERSION, this was a spelling error. + + * m4.c: Declare version[], remove #include "version.h". + * version.h: Deleted. + * Makefile.in: Remove references to version.h. + + * output.c (shipout_text): Centralize all `#line NUM ["FILE"]' + production, by using a simpler and more robust algorithm. This + solves the problem of synclines sometimes written in the middle of + an output line. Delete sync_line() and output_lines variable. + * m4.h: Remove sync_line prototype and output_lines declaration. + * input.c (next_char), output.c (shipout_text): Remove references + to output_lines. + * input.c (push_file, pop_file): Merely put the value -1 in + output_current_line instead of calling sync_line, for delaying a + single `#line NUM FILE' before next output line. Do not test + for sync_output, because this is unnecessary clutter. + * output.c (make_divertion, insert_divertion): Idem. + * input.c: Rename must_advance_line to start_of_input_line, for + consistency. + + * debug.c (trace_header): Select a new debug line format, which + better complies with GNU standards for formatting error messages. + With option `-dfl', M-x next-error might be used on the output. + * m4.c (vmesg): Adjust format of error output to GNU standards. + * m4.texinfo: Adjust examples for `make check' to work. + + * m4.h, builtin.c, debug.c, input.c, macro.c, path.c: Use upper + case for enum debug_info constants, which were all lower case. + + * builtin.c (m4_regexp, m4_patsubst): Use re_search instead of + re_search_2. + * lib/regex.[ch]: Use new version from textutils 1.3.6, with some + collected patches. I tried a few times using newer regex.[ch], it + mysteriously stopped aborting with this one. Insecure feeling... + * lib/Makefile.in: Distribute regex.[ch].old, just in case! + +1992-12-18 François Pinard <pinard@iro.umontreal.ca> + + * m4.c: Change `--no-warnings' to `--silent'. + Reported by David MacKenzie. + + * m4.c: Put all M4OPTS code upon IMPLEMENT_M4OPTS control, and + leave it off for now. See comment in m4.c for justification. + Reported by David MacKenzie. + + * configure.in: Replace AC_USG by AC_HAVE_HEADERS(string.h). + * m4.h, ansi2knr.c, lib/regex.h: Replace USG by HAVE_STRING_H. + + * Makefile.in: Add a new `info' goal. Use macro MAKEINFO. + + * Makefile.in: Ensure recursive cleaning is done before local + cleaning for all clean goals. + + * builtin.c (ntoa): Ensure the value is always interpreted as a + signed quantity, whatever the radix is. + +1992-11-18 Jim Meyering <meyering@idefix> + + * builtin.c, format.c, input.c: Split long lines. + * m4.c: Use typedef macro_definition instead of struct + macro_definition. + * symtab.c: Use typedef symbol instead of struct symbol. + +1992-11-17 François Pinard <pinard@iro.umontreal.ca> + + * *.[ch]: Remove all trailing whitespace, in code and comments. + + * configure.in: Find some awk. + * Makefile.in: Add $(AWK) to MDEFINES. + * checks/Makefile.in: Transmit $(AWK) to get_them. + * checks/get_them: Use $AWK instead of gawk. Add a close in the + awk script when switching files, because without this, mawk runs + out of file descriptors. + +1992-11-16 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (realclean): Delete m4.info*. + Reported by Jim Meyering. + + * Makefile.in: Adjust and link with checks/Makefile. + * checks/Makefile.in: New. + * configure.in: Output checks/Makefile. + + * checks/get_them: Have the dnl header of each test more + recognizable by next-error, also use a better message. + +1992-11-16 Jim Meyering <meyering@idefix> + + * m4.h [__GNUC__]: Use __volatile__ instead of `volatile.' + And use that only if __GNUC__ since we're using it's GCC-specific + semantics that tell the compiler the associated function doesn't + return. + + * builtin.c (substitute): Don't use character as an array index. + (dumpdef_cmp): Make formal arguments `const void *' to avoid + warnings with gcc -W -Wall on systems with qsort prototype. + (m4_errprint): Cast obstack_finish to `char *' to avoid warnings + from gcc -W -Wall. + + * eval.c (most functions): Add parentheses to assignments used + as truth values go avoid warnings from gcc -Wall. + + * input.c, m4.c, output.c, path.c, symtab.c: Declare static + any functions that don't need external scope. + + * builtin.c, debug.c, format.c, m4.c, m4.h, macro.c, symtab.c + (many functions and arrays): Declare `const'. + +1992-11-15 François Pinard <pinard@iro.umontreal.ca> + + * *.[ch]: Rename nil to NULL, using the declaration from <stdio.h>, + removing the declaration from m4.h. Also rename false to FALSE + and true to TRUE. + + * lib/Makefile.in (Makefile): New goal. + + * Makefile.in, lib/Makefile.in: Add a .c.o rule, so CFLAGS is not + so heavily loaded. It gets more easily overridable, calling make. + Reported by Jim Meyering. + + * Makefile.in (dist): Get .fname from the current directory name, + instead of from version.h. I need updating many files manually, + when the version changes, version.h is just one of them. + +1992-11-14 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Remove the tag `boolean' on the enum introducing typedef + `boolean'. This tag conflicts with <sys/types.h> on SVR4. + Reported by Tom McConnell. + +1992-11-13 François Pinard <pinard@iro.umontreal.ca> + + * m4.texinfo: Correct the examples for 33.divert, 38.divnum, + 39.cleardiv, which were describing missing or spurious newlines. + Modify examples 52.eval, 53.esyscmd and 54.sysval so the results + do not depend on machine word size, `/bin/false' implementation, + or `wc' output format. `make check' is more dependable, now. + + * checks/check_them: Summarize the failed tests by listing their + name, at end. If none, issue `All checks successful'. Output + `Checking' instead of `Input file:'. + + * checks/get_them, checks/check_them: Reindented. + + * Makefile.in (dist): chmod a+r before making the tar file. + +1992-11-12 François Pinard <pinard@iro.umontreal.ca> + + * builtin.c (m4_dnl): Diagnose any parameter to `dnl'. + + * input.c (next_token): Reinitialize token_buttom just after using + it as a watermark with obstack_free. Or else, a future token, big + enough for triggering reallocation of the obstack chunk, could + void the initialized value of token_buttom, later causing panic in + obstack_free. Rename token_buttom to token_bottom everywhere. + + * m4.h: Before declaring errno, first include <errno.h> and + ensure that it does not define errno. + Reported by Richard Stallman. + +1992-11-11 François Pinard <pinard@iro.umontreal.ca> + + * builtin.c: Define and use DECLARE macro for builtins. + + * builtin.c (m4_ifelse): Avoid any diagnostic when exactly one + argument, this is a common idiom for introducing long comments. + + * builtin.c (m4_ifelse): If 3n + 2 arguments, diagnose missing + arguments. The last argument was silently ignored. + + * m4.c (cmd_error): Add a missing semicolon before va_end(). + +1992-11-10 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in: Now handle protoized sources. Define and use U. + Compile and use ansi2knr with old compilers. Update DISTFILES. + Add `aclocal.m4' to `configure' dependencies. + * ansi2knr.c: New, from Ghostscript distribution. + * configure.in: Define U through FP_PROTOTYPES for old compilers. + Add AC_ISC_POSIX, AC_CONST, AC_SIZE_T. + * aclocal.m4: New, provide FP_PROTOTYPES. + * m4.h: Conditionnaly protoized through Args, save for varags. + * builtin.c: Protoized. Then: + Include <sys/types.h> if size_t is not defined, before "regex.h". + (m4_ifelse): Fetch built-in name properly for diagnostic. + (m4_dumpdef): Remove wrong (char *) cast calling dump_symbol. + (m4_regexp): Add const to `msg' declaration. + (m4_patsubst): Add const to `msg' declaration. + * debug.c: Protoized, save for varargs. + * eval.c: Protoized. + * format.c: Protoized. + * input.c: Protoized. + * m4.c: Protoized, save for varargs. Then: + (xfree): Accept void * instead of char *. + (xmalloc): Return void * instead of char *. + (xrealloc): Accept and return void * instead of char *. + * macro.c: Protoized. + * output.c: Protoized. + * path.c: Protoized. Then cast some (char *) over xmalloc's. + * symtab.c: Protoized. + +1992-11-06 François Pinard <pinard@iro.umontreal.ca> + + * m4.texinfo: Remove directory from diagnostics in 30.include, + 51.eval, 56.errprint and 57.m4exit tests. + + * m4.h: Remove declarations for int or void system functions, they + cause more conflicting trouble than they make good. + + * configure.in: Avoid configuration header file. Add some tests. + * m4.h: Remove #include "config.h". + * Makefile.in, lib/Makefile.in: Implement Autoconf interface. + Then, rewritten for better compliance with GNU standards. + +1992-11-05 François Pinard <pinard@iro.umontreal.ca> + + * format.c (format): Avoid syntax error if not HAVE_EFGCVT, + because of a misplaced #endif. + + * Many *.[hc] files: Correct intra-line spacing here and there, + according to GNU indent 1.6 advice. + + * configure.in: New, using Autoconf 1.2. + * m4.h: Reverse NO_MEMORY_H to NEED_MEMORY_H. + * Delete old configure.in, configure, etc/configure.in, + etc/configure, lib/configure.in, lib/configure and config/*. + Reported by Jason Merrill. + + * symtab.c (hash): Change (char) NULL to '\0'. + Reported by Jason Merrill. + + * Delete .vers, etc/newdist.sh, etc/newvers.sh and + etc/nextvers.sh. Release numbers will be edited `by hand'. + * version.h: De-automatize, force value in. + + * m4.c: Changes in order to use a newer getopt.h. + Reported by David MacKenzie. + + * checks/: New name for examples/. + * checks/get_them: New location for etc/get_examples. + * checks/check_them: New location for etc/check_examples. + * Makefile.in, checks/get_them, checks/check_them: Adjust. + * lib/vfprintf.c: New location for etc/vfprintf.c. + * Delete empty etc/. + * examples/: New name for test/. + +1992-03-10 François Pinard <pinard@iro.umontreal.ca> + + * Makefile.in (check): Add m4 as dependency. + + * m4.c: Accept --no-warnings instead of --no_warnings, and + --no-gnu-extensions instead of --no_gnu_extensions. Make the + usage message more informative. + Reported by David MacKenzie. + +1992-03-09 François Pinard <pinard@iro.umontreal.ca> + + * etc/check_examples: New name for check_examples.sh. + * etc/get_examples: New name for get_examples.sh. + * Makefile.in, etc/Makefile.in: Use new names. + + * Makefile.in: Transmit $(CC) while making in lib. + + * Many *.[hc] files: GNU indent'ed, with further fine tuning of + code disposition by hand. + +1992-03-08 François Pinard <pinard@iro.umontreal.ca> + + * m4.h: Delete definitions for abort() and exit(). + Reported by Richard Stallman. + + * config/hmake-unicos, config/s-unicos.h: New files. + Reported by Hal Peterson. + + * eval.c (exp_term): Have N^0 return 1. + Reported by Michael Fetterman. + + * eval.c, input.c, m4.h: Remove last comma in enums. + Reported by Mike Lijewski. + + * Transfer of maintenance duties from René to François. + +1991-10-24 René Seindal <seindal@diku.dk> + + * Release 1.0. Many thanks to those, who provided me with bug + reports and feedback. + + * Uses GNU configure, taken from the gdb distribution. + + * Uses GNU getopt(), with long option names. + + * The -Q/+quiet option is added, which suppresses warnings about + missing or superflous arguments to built-in macros. + + * Added default options via the M4OPTS environment variable. + + * The built-in format can now be configured to use sprintf as + the formatting engine, for systems without [efg]cvt(3). + + * GNU library code is moved to the ./lib subdirectory; other + utility files are now in ./etc. + + * Several minor bugs have been fixed. + +1991-07-26 René Seindal <seindal@diku.dk> + + * Fixed various bugs. Release 0.99, manual 0.09. Many thanks to + Francois Pinard and Roland H. Pesch for providing me with reports. + + * The builtins incr and decr are now implemented without use of + eval. + + * The builtin indir is added, to allow for indirect macro calls + (allows use of "illegal" macro names). + + * The debugging and tracing facilities has been enhanced + considerably. See the manual for details. + + * The -tMACRO option is added, marks MACRO for tracing as soon + as it is defined. + + * Builtins are traced after renaming iff they were before. + + * Named files can now be undiverted. + + * The -Nnum option can be used to increase the number of + divertions available. + + * Calling changecom without arguments now disables all comment + handling. + + * The function m4_patsubst() is now consistently declared + static. + + * A bug in dnl is fixed. + + * A bug in the multi-character quoting code is fixed. + + * Several typos in the manual has been corrected. More probably + persist. + + * The m4.info file is now installed along with the program. + +1990-11-15 René Seindal <seindal@diku.dk> + + * Updated and enhanced version. Release 0.75, manual 0.07. + + * Implemented search path for include files (-I option and + M4PATH envronment variable). + + * Implemented builtin "format" for printf-like formatting. + + * Implemented builtin "regexp" for searching for regular + expressions. + + * Implemented builtin "patsubst" for substitution with regular + expressions. + + * Implemented builtin "esyscmd", which expands to a shell + commands output. + + * Implemented "__file__" and "__line__" for use in error + messages. + + * Implemented character ranges in "translit". + + * Implemented control over debugging output. + + * Implemented multi-character quotes. + + * Implemented multi-character comment delimiters. + + * Changed predefined macro "gnu" to "__gnu__". + + * Changed predefined macro "unix" to "__unix__", when the -G + option is not used. With -G, "unix" is still defined. + + * Changed "shift", "$@" and "$*" to not insert spaces afters + commas. + + * Added program name to error messages. + + * Fixed two missing null bytes bugs. + +1990-01-22 René Seindal <seindal@diku.dk> + + * Initial beta release. Release 0.50, manual 0.05. + +</PRE> + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/download.htm b/examples/WWW/download.htm new file mode 100644 index 00000000..9b714f32 --- /dev/null +++ b/examples/WWW/download.htm @@ -0,0 +1,302 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Download</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Download</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<P> +In the download area there are usually several version +present. Please take only the latest. +</P> + + +<P> +The files are name <TT>m4-1.4<I>X</I>.tar.gz</TT> where X is a letter. +</P> + + +<P> +<A HREF="ftp://ftp.seindal.dk/pub/rene/gnu/">Download latest +development version</A>. +</P> + + +<P> +<A HREF="ftp://ftp.seindal.dk/pub/rene/gnu/m4-1.4.tar.gz">Download +latest stable version</A>. +</P> + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/features.htm b/examples/WWW/features.htm new file mode 100644 index 00000000..ce8f1895 --- /dev/null +++ b/examples/WWW/features.htm @@ -0,0 +1,380 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - New feaures since version 1.4</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>New feaures since version 1.4</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<P> +Please look at the <A HREF="news.htm">NEWS</A> and the <A HREF="changelog.htm">ChangeLog</A> for all the gory details. +</P> + + +<DL> +<DT><B>GNU m4 uses GNU Automake and GNU Autoconf for configuration.</B></DT> + +<DD> +<P> +This has been long overdue and now hit is done thanks to Erick +Branderhorst. +</P> + +</DD> + + +<DT><B>GNU m4 uses GNU gettext for internationalisation.</B></DT> + +<DD> +<P> +GNU m4 now speaks several languages. Translations for +german french italian japanese dutch polish romenian and swedish +have been made. +</P> + +</DD> + + +<DT><B>Support for multiple precision arithmetic in eval.</B></DT> + +<DD> +<P> +If appropriately configured GNU m4 can now do multiple precision +arithmetic in the build in macro 'eval'. If not configured GNU m4 +will use the largest integer available for its calculations. +</P> + +</DD> + + +<DT><B>An input syntax table to change how input is parsed.</B></DT> + +<DD> +<P> +A new build in macro 'changesyntax' allows finer control over how input +characters are parsed into input tokens. It is no possible to have +several one character quote strings or comment delimiters to change the +format of macro calls to use active characters like in TeX and probably +most useful to change what input characters are treated as letters when +looking for macro calls. +</P> + + +<P> +See the <A HREF="man/m4_7.html#SEC41">manual section</A> for more details. +</P> + +</DD> + + +<DT><B>Support for loadable modules.</B></DT> + +<DD> +<P> +GNU m4 now has rudimentary support for dynamic loading of +compiled modules at runtime. A module can define any number of new build +in macros which will be indistinguishable from the standard set of +build in macros. Modules can also override existing build in macros. +</P> + + +<P> +Module support for GNU m4 still needs some work. +</P> + + +<P> +See the <A HREF="modules.htm">separate README file for modules</A> +</P> + + +</DD> + + +<DT><B>Better control of sync-lines generation.</B></DT> + +<DD> +<P> +The new build in macro 'syncoutput' allows better control of the +generation of sync-lines. They can no be turned on or off at +will. +</P> + +</DD> + + + +</DL> + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/feedback.htm b/examples/WWW/feedback.htm new file mode 100644 index 00000000..f6a991d1 --- /dev/null +++ b/examples/WWW/feedback.htm @@ -0,0 +1,297 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Feedback</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Feedback</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<P> +Bug reports should be sent to <A HREF="mailto:bug-m4@gnu.org">bug-m4@gnu.org</A>. +</P> + + +<P> +Generel discussion about GNU m4 should take place on +<A HREF="mailto:m4-forum@seindal.dk">m4-forum</A>. +</P> + + +<P> +Informal comments about this site and GNU m4 can be sent to +<A HREF="mailto:m4-feedback@seindal.dk">m4-feedback</A>. +</P> + + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/index.htm b/examples/WWW/index.htm new file mode 100644 index 00000000..8e739aef --- /dev/null +++ b/examples/WWW/index.htm @@ -0,0 +1,319 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Development site</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Development site</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<H2>Current development version is 1.4l.</H2> + + +<P> +Development versions contain new features and experiments that might +or might not make it into the next official release. The current +development version contains among other things (browse the +<A HREF="features.htm">new features</A> for more detail): +</P> + + +<UL> + + <LI> Uses GNU Automake and GNU Autoconf for configuration. + + <LI> Uses GNU gettext for internationalisation. + + <LI> Support for multiple precision arithmetic in eval. + + <LI> An input syntax table to change how input is parsed. + + <LI> Support for loadable modules. + + <LI> Better control of sync-lines generation. + + <LI> Various bug-fixes. + +</UL> + + +<P> +A new release is expected ready for December 1998. +</P> + + +<P> +GNU <TT>m4</TT> 1.4 is from october 1994 and can be considered stable. +</P> + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/lists.htm b/examples/WWW/lists.htm new file mode 100644 index 00000000..afa2b9be --- /dev/null +++ b/examples/WWW/lists.htm @@ -0,0 +1,320 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Mailing lists</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Mailing lists</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + + +<H3>There are two mailing lists for GNU m4</H3> + + +<DL> +<DT><B><A HREF="mailto:m4-forum@seindal.dk">m4-forum@seindal.dk</A></B></DT> + +<DD> +<P> +This list is intended for discussions between people interested +and/or participating in the further development of m4. +</P> + +</DD> + + +<DT><B>m4-announce@seindal.dk</B></DT> + +<DD> +<P> +Announcements regarding GNU m4 will posted here. +</P> + +<P> +The volume will certainly be very low. +</P> + +</DD> + + + +</DL> + + +<P> +Currently these lists are maintained manually. Send a message to <A HREF="mailto:rene@seindal.dk">rene@seindal.dk</A> +saying whether you want to subscribe or unsubscribe to any of these +lists. +</P> + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/m4lib/bugs.m4 b/examples/WWW/m4lib/bugs.m4 new file mode 100644 index 00000000..f3204317 --- /dev/null +++ b/examples/WWW/m4lib/bugs.m4 @@ -0,0 +1,52 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Known bugs in GNU m4 \__m4_version__]) + +\divert(1) +\h2([Known bugs in GNU m4]) + +\define([fixed], [\p([Fixed in version 1.4$1])]) + +\define([notme], [\p([A <A +HREF="mailto:m4-feedback@seindal.dk?subject=GNU m4: \defn([_item])" +>volunteer</A> is badly needed for this, as I have no way of testing +this myself.])]) + +\ul([ + +\item([undivert], [undivert(0) might read from standard output], + +[\p([If calling \tt(undivert(0)) when diverting to a non-zero diversion +will cause m4 to read from standard output in an attempt to bring back +diversion 0, which is not possible.]) + +\fixed(n) + +]) + +\item([sigaltstack], [failure if sigaltstack or sigstack returns ENOSYS], + +[\p([If stack overflow detection is configured but the system doesn't +support sigaltstack(2) or sigstack(2), m4 fails when the system call +returns ENOSYS. It should silently revert to default behaviour.]) + +\notme +]) + +]) + +\p([See also the \link(todo.htm, TODO) file.]) + +\print_items + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) + + +\item([], [], + +[\p([]) + +]) diff --git a/examples/WWW/m4lib/changelog.m4 b/examples/WWW/m4lib/changelog.m4 new file mode 100644 index 00000000..cdcab269 --- /dev/null +++ b/examples/WWW/m4lib/changelog.m4 @@ -0,0 +1,18 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([ChangeLog]) + +\divert(1) + +<PRE>\dnl +\changesyntax([A<>])\dnl +\changequote(,)\dnl +\include(m4/ChangeLog) +\changequote([,])\dnl +\changesyntax([O<>])\dnl +</PRE> + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/download.m4 b/examples/WWW/m4lib/download.m4 new file mode 100644 index 00000000..a26eedfb --- /dev/null +++ b/examples/WWW/m4lib/download.m4 @@ -0,0 +1,21 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Download]) + +\divert(1) + +\p(In the download area there are usually several version +present. Please take only the latest.) + +\p(The files are name \tt(m4-1.4\i(X).tar.gz) where X is a letter.) + +\p(\link([ftp://ftp.seindal.dk/pub/rene/gnu/], [Download latest +development version]).) + +\p(\link([ftp://ftp.seindal.dk/pub/rene/gnu/m4-1.4.tar.gz],[Download +latest stable version]).) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/features.m4 b/examples/WWW/m4lib/features.m4 new file mode 100644 index 00000000..67bb8b2a --- /dev/null +++ b/examples/WWW/m4lib/features.m4 @@ -0,0 +1,62 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([New feaures since version 1.4]) + +\divert(1) + +\p(Please look at the \link(news.htm, NEWS) and the \link(changelog.htm, +ChangeLog) for all the gory details.) + +\dl( +\dt(\b(GNU m4 uses GNU Automake and GNU Autoconf for configuration.)) + +\dd(\p(This has been long overdue, and now hit is done thanks to Erick +Branderhorst.)) + +\dt(\b(GNU m4 uses GNU gettext for internationalisation.)) + +\dd(\p(GNU m4 now speaks several languages. Translations for +german, french, italian, japanese, dutch, polish, romenian and swedish +have been made.)) + +\dt(\b(Support for multiple precision arithmetic in eval.)) + +\dd(\p(If appropriately configured, GNU m4 can now do multiple precision +arithmetic in the build in macro 'eval'. If not configured, GNU m4 +will use the largest integer available for its calculations.)) + +\dt(\b(An input syntax table to change how input is parsed.)) + +\dd(\p(A new build in macro 'changesyntax' allows finer control over how input +characters are parsed into input tokens. It is no possible to have +several one character quote strings or comment delimiters, to change the +format of macro calls, to use active characters like in TeX, and probably +most useful, to change what input characters are treated as letters when +looking for macro calls.) + +\p(See the \link(man/m4_7.html#SEC41, manual section) for more details.)) + +\dt(\b(Support for loadable modules.)) + +\dd(\p(GNU m4 now has rudimentary support for dynamic loading of +compiled modules at runtime. A module can define any number of new build +in macros, which will be indistinguishable from the standard set of +build in macros. Modules can also override existing build in macros.) + +\p(Module support for GNU m4 still needs some work.) + +\p(See the \link(modules.htm, separate README file for modules)) +) + +\dt(\b(Better control of sync-lines generation.)) + +\dd(\p(The new build in macro 'syncoutput' allows better control of the +generation of sync-lines. They can no be turned on or off at +will.)) + +) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/feedback.m4 b/examples/WWW/m4lib/feedback.m4 new file mode 100644 index 00000000..f61d63e5 --- /dev/null +++ b/examples/WWW/m4lib/feedback.m4 @@ -0,0 +1,20 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Feedback]) + +\divert(1) + +\p(Bug reports should be sent to \link(mailto:bug-m4@gnu.org, +bug-m4@gnu.org).) + +\p(Generel discussion about GNU m4 should take place on +\link(mailto:m4-forum@seindal.dk, m4-forum).) + +\p(Informal comments about this site and GNU m4 can be sent to +\link(mailto:m4-feedback@seindal.dk, m4-feedback).) + + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/html.m4 b/examples/WWW/m4lib/html.m4 new file mode 100644 index 00000000..50330af2 --- /dev/null +++ b/examples/WWW/m4lib/html.m4 @@ -0,0 +1,119 @@ +\define([n], [ +]) + +\define([concat], [\ifelse($#, 0, , + $#, 1, [$1], + [$1 \concat(\shift($@))])]) + +\define([toupper], [\translit([$*], [a-z], [A-Z])]) + +\define([container], +[\pushdef([_tag], \toupper([$1]))\dnl +\ifelse($#, 1, [<\_tag></[\_tag]>], + $#, 2, [<\_tag>$2</\_tag>], + $#, 3, [<\_tag $2>$3</\_tag>], + [<\_tag $2>\concat(\shift(\shift($@)))</\_tag>])\dnl +\popdef([_tag])\dnl +]) + +\define([large_container], +[\pushdef([_tag], \toupper([$1]))\dnl +\ifelse($#, 1, [<\_tag></\_tag>\n], + $#, 2, [<\_tag>\n[]$2\n</\_tag>\n], + $#, 3, [<\_tag $2>\n[]$3\n</\_tag>\n], + [<\_tag $2>\n\concat(\shift(\shift($@)))\n</\_tag>\n])\dnl +\popdef([_tag])\dnl +]) + +\define([large_simple_container], +[\pushdef([_tag], \toupper([$1]))\dnl +<\_tag>\n\concat(\shift($@))\n</\_tag>\n\dnl +\popdef([_tag])\dnl +]) + +\define([simple_container], +[\pushdef([_tag], \toupper([$1]))\dnl +<\_tag>\concat(\shift($@))</\_tag>\dnl +\popdef([_tag])\dnl +]) + +\define([simple_tag], +[\pushdef([_tag], \toupper([$1]))\dnl +\ifelse([$2], [], [<\_tag>], [<\_tag $2>])\dnl +\popdef([_tag])\dnl +]) + +\define([doctype], [\simple_tag([$0], $@)]) + +\define([html], [\large_simple_container([$0], $@)]) +\define([head], [\large_simple_container([$0], $@)]) +\define([title], [\simple_container([$0], $@)]) + +\define([meta], [\n<META NAME="[$1]" CONTENT="[$2]">]) +\define([http_equiv], [\n<META HTTP-EQUIV="[$1]" CONTENT="[$2]">]) + +\define([body], [\large_container([$0], $@)]) + +\define([center], [\large_simple_container([$0], $@)]) +\define([right], [\large_simple_container([$0], $@)]) +\define([left], [\large_simple_container([$0], $@)]) +\define([div], [\large_container([$0], $@)]) + +\define([b], [\simple_container([$0], $@)]) +\define([i], [\simple_container([$0], $@)]) +\define([tt], [\simple_container([$0], $@)]) + +\define([table], [\large_container([$0], $@)]) +\define([tr], [\large_container([$0], $@)]) +\define([td], [\large_container([$0], $@)]) +\define([th], [\large_container([$0], $@)]) + +\define([link], [<A HREF="$1">\shift($@)</A>]) +\define([target], [<A NAME="$1">\shift($@)</A>]) + +\define([font], [\n\container([$0], $@)\n]) + +\define([h1], [\n\container([$0], $@)\n]) +\define([h2], [\n\container([$0], $@)\n]) +\define([h3], [\n\container([$0], $@)\n]) +\define([h4], [\n\container([$0], $@)\n]) +\define([h5], [\n\container([$0], $@)\n]) +\define([h6], [\n\container([$0], $@)\n]) + +\define([p], [\large_simple_container([$0], $@)]) + + +\define([ul], [\large_container([$0], $@)]) +\define([ol], [\large_container([$0], $@)]) + +\define([li], [\simple_tag([$0], $@)]) + +\define([dl], [\large_simple_container([$0], $@)]) +\define([dt], [\simple_container([$0], $@)]) +\define([dd], [\large_simple_container([$0], $@)]) + +\define([br], [\simple_tag([$0], $@)]) +\define([hline], [\simple_tag([$0], $@)]) + +\define([pre], [\simple_container([$0], $@)]) + + + +\define([set_title], [\define([_TITLE], [$*])]) +\set_title(_TITLE) + +\define([set_author], [\define([_AUTHOR], [$*])]) +\set_author() + +\define([set_generator], [\define([_GENERATOR], [$*])]) +\set_generator([GNU m4 \__m4_version__]) + +\define([set_keywords], [\define([_KEYWORDS], [$*])]) +\set_keywords() + +\define([set_body], [\define([_BODY], [$*])]) +\set_body() + +\define([meta_if_set], + [\ifelse(\defn([_$1]), [], [], \meta([$1], \defn([_$1])))]\dnl +) diff --git a/examples/WWW/m4lib/index.m4 b/examples/WWW/m4lib/index.m4 new file mode 100644 index 00000000..043faa35 --- /dev/null +++ b/examples/WWW/m4lib/index.m4 @@ -0,0 +1,36 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Development site]) + +\divert(1) +\h2([Current development version is \__m4_version__.]) + +\p([Development versions contain new features and experiments that might +or might not make it into the next official release. The current +development version contains among other things (browse the +\link([features.htm], [new features]) for more detail):]) + +\ul([ + \li Uses GNU Automake and GNU Autoconf for configuration. + + \li Uses GNU gettext for internationalisation. + + \li Support for multiple precision arithmetic in eval. + + \li An input syntax table to change how input is parsed. + + \li Support for loadable modules. + + \li Better control of sync-lines generation. + + \li Various bug-fixes. +]) + +\p([A new release is expected ready for December 1998.]) + +\p([GNU \tt(m4) 1.4 is from october 1994 and can be considered stable.]) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/layout.m4 b/examples/WWW/m4lib/layout.m4 new file mode 100644 index 00000000..6feb08ec --- /dev/null +++ b/examples/WWW/m4lib/layout.m4 @@ -0,0 +1,50 @@ +\divert(-1); +The semicolons are just to get GNU Emacs C mode to indent properly. + +\define([C_TEXT], [text="#000000"]); +\define([C_LINK], [link="#0000EF"]); +\define([C_ALINK], [vlink="#51188E"]); +\define([C_VLINK], [alink="#FF0000"]); +\define([C_BG1], [bgcolor="#FFCC99"]); +\define([C_BG2], [bgcolor="#FF9900"]); +\define([C_BG3], [bgcolor="#CC6600"]); + +\define([DO_HEADER], + [\head([\title([GNU m4 - \defn([_TITLE])])], + [\meta_if_set([AUTHOR])], + [\meta_if_set([GENERATOR])], + [\meta_if_set([KEYWORDS])], + )]); + +\define([DO_BODY], + [\body([\C_TEXT \C_BG1 \C_LINK \C_VLINK \C_ALINK], + [\table([cellpadding=5 width="100%"], + [\tr([align=left valign=bottom], + [\td([align=center valign=center colspan="3" width="100%" \C_BG2], + [\h1([GNU m4])], + [\h2(\defn([_TITLE]))], + )], + )], + [\tr([], + [\td([align=left valign=top width="15%" \C_BG2], + [\include([menu.m4])], + )], + [\td([align=left valign=top width="90%"], + [$*], + )], + )], + )], + )] + ); + +\define([DO_LAYOUT], + [\doctype([HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"]) +\html([\DO_HEADER], [\DO_BODY([$*])])] + ); + +\define([<], [<]); +\define([>], [>]); + +\define([showlink], [\link($1, $1)]); +\define([mailto], [\link(mailto:$1, $1)]); + diff --git a/examples/WWW/m4lib/lists.m4 b/examples/WWW/m4lib/lists.m4 new file mode 100644 index 00000000..cc710eba --- /dev/null +++ b/examples/WWW/m4lib/lists.m4 @@ -0,0 +1,32 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Mailing lists]) + +\define([me], \link([mailto:rene@seindal.dk], [rene@seindal.dk])) + +\divert(1) + +\h3(There are two mailing lists for GNU m4) + +\dl( + +\dt(\b(\link(mailto:m4-forum@seindal.dk, m4-forum@seindal.dk))) + +\dd(\p(This list is intended for discussions between people interested +and/or participating in the further development of m4.)) + +\dt(\b(m4-announce@seindal.dk)) + +\dd(\p(Announcements regarding GNU m4 will posted here.) +\p(The volume will certainly be very low.)) + +) + +\p(Currently these lists are maintained manually. Send a message to \me +saying whether you want to subscribe or unsubscribe to any of these +lists.) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/menu.m4 b/examples/WWW/m4lib/menu.m4 new file mode 100644 index 00000000..1a770b63 --- /dev/null +++ b/examples/WWW/m4lib/menu.m4 @@ -0,0 +1,35 @@ +\pushdef([header], [\tr([\td([\C_BG3], [\p([\b([$1])])])])]) +\pushdef([row], [\tr([\td([\font([size=-1], [\p([\b([\link([$1], [$2])])])])])])]) + +\table([align=left valign=top columns=1], + [\header([Generel info])], + [\row([whatis.htm], [What is m4])], + [\row([features.htm], [Features])], + [\row([uses.htm], [Uses of m4])], + + [\header([Documentation])], + [\row([man/m4_toc.html], [Manual])], + + [\header([Source files])], + [\row([readme.htm], [README])], + [\row([todo.htm], [TODO])], + [\row([news.htm], [NEWS])], + [\row([changelog.htm], [ChangeLog])], + [\row([thanks.htm], [Contributors])], + [\row([m4/], [Browse it])], + + [\header([The Future])], + [\row([modules.htm], [Modules])], + [\row([visions.htm], [Visions])], + + [\header([Development])], + [\row([lists.htm], [Mailing-lists])], + [\row([feedback.htm], [Feedback])], + [\row([download.htm], [Download])], + + [\header([Examples])], + [\row([thissite.htm], [This site])], + ) + +\popdef([header]) +\popdef([row]) diff --git a/examples/WWW/m4lib/modules.m4 b/examples/WWW/m4lib/modules.m4 new file mode 100644 index 00000000..b9c148f1 --- /dev/null +++ b/examples/WWW/m4lib/modules.m4 @@ -0,0 +1,18 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Modules]) + +\divert(1) + +<PRE>\dnl +\changesyntax([A<>])\dnl +\changequote(,)\dnl +\include(m4/modules/README) +\changequote([,])\dnl +\changesyntax([O<>])\dnl +</PRE> + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/news.m4 b/examples/WWW/m4lib/news.m4 new file mode 100644 index 00000000..e5da0d89 --- /dev/null +++ b/examples/WWW/m4lib/news.m4 @@ -0,0 +1,18 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([NEWS - History of user-visible changes]) + +\divert(1) + +<PRE>\dnl +\changesyntax([A<>])\dnl +\changequote(,)\dnl +\include(m4/NEWS) +\changequote([,])\dnl +\changesyntax([O<>])\dnl +</PRE> + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/readme.m4 b/examples/WWW/m4lib/readme.m4 new file mode 100644 index 00000000..1612c7d1 --- /dev/null +++ b/examples/WWW/m4lib/readme.m4 @@ -0,0 +1,18 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([README]) + +\divert(1) + +<PRE>\dnl +\changesyntax([A<>])\dnl +\changequote(,)\dnl +\include(m4/README) +\changequote([,])\dnl +\changesyntax([O<>])\dnl +</PRE> + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/setup.m4 b/examples/WWW/m4lib/setup.m4 new file mode 100644 index 00000000..310b65f8 --- /dev/null +++ b/examples/WWW/m4lib/setup.m4 @@ -0,0 +1,7 @@ +divert(-1) +changequote([,]) +changecom([<!--], [-->]) +changesyntax([@\]) + +\include([html.m4]) +\include([layout.m4]) diff --git a/examples/WWW/m4lib/test.m4 b/examples/WWW/m4lib/test.m4 new file mode 100644 index 00000000..9fdef40b --- /dev/null +++ b/examples/WWW/m4lib/test.m4 @@ -0,0 +1,9 @@ +include(`_setup.m4') +\include([_html.m4]) +\include([_layout.m4]) + +\set_title([Development site]) + +\divert + +\DO_BODY([BODY]) diff --git a/examples/WWW/m4lib/thanks.m4 b/examples/WWW/m4lib/thanks.m4 new file mode 100644 index 00000000..61928d07 --- /dev/null +++ b/examples/WWW/m4lib/thanks.m4 @@ -0,0 +1,18 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([People who have contributed to m4]) + +\divert(1) + +<PRE>\dnl +\changesyntax([A<>])\dnl +\changequote(,)\dnl +\include(m4/THANKS) +\changequote([,])\dnl +\changesyntax([O<>])\dnl +</PRE> + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/thissite.m4 b/examples/WWW/m4lib/thissite.m4 new file mode 100644 index 00000000..0d4d772b --- /dev/null +++ b/examples/WWW/m4lib/thissite.m4 @@ -0,0 +1,39 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([This site]) + +\divert(1) + +\p(This GNU m4 site is maintained by René Seindal, +(\mailto(rene@seindal)).) + +\p(All files are generated using GNU m4 \__m4_version__. You can view +the \link(m4lib/, source files). They are very simple. They use some +features from Gnu m4 1.4l) + +\p(The basic M4 definitions of quotes, comments, escapes are in +\showlink(m4lib/setup.m4). This is first included by all files to +configure the enviroment correctly for the other files. To avoid have +macros called by accident, an escape character is defined with +changesyntax. \i(This is a new feature in m4 1.4l).) + +\p(Some fairly general macros to generate various HTML construct are +found in \showlink(m4lib/html.m4). There are macros for simple tags, +containers with and with attributes, links and a few utility macros.) + +\p(The visual aspects of the pages are in \showlink(m4lib/layout.m4). +The macros herein generate the complete HTML structure for the pages. +There are macros for making the header and the body of the document.) + +\p(The page body is passed to the layout definitions as an argument. As +the text can be large, it is first diverted and the text passed to the +layout macros is simply a call to undivert. That way a very large text +can be passed around with very little cost. This page is made with +\link(m4lib/thissite.m4, these definitions).) + +\p(There is a single file for each HTML file.) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/tmpl.m4 b/examples/WWW/m4lib/tmpl.m4 new file mode 100644 index 00000000..8262d293 --- /dev/null +++ b/examples/WWW/m4lib/tmpl.m4 @@ -0,0 +1,11 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([]) + +\divert(1) +\h2([]) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/todo.m4 b/examples/WWW/m4lib/todo.m4 new file mode 100644 index 00000000..7a22c151 --- /dev/null +++ b/examples/WWW/m4lib/todo.m4 @@ -0,0 +1,18 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([TODO - Things still to be done]) + +\divert(1) + +<PRE>\dnl +\changesyntax([A<>])\dnl +\changequote(,)\dnl +\include(m4/TODO) +\changequote([,])\dnl +\changesyntax([O<>])\dnl +</PRE> + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/uses.m4 b/examples/WWW/m4lib/uses.m4 new file mode 100644 index 00000000..75f7b6ae --- /dev/null +++ b/examples/WWW/m4lib/uses.m4 @@ -0,0 +1,36 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([Current uses of m4]) + +\divert(1) + +\p(The MTA sendmail uses \tt(m4) for generating configuration files.) + +\p(\link(http://www.gnu.org/software/autoconf/autoconf.html, GNU +Autoconf) uses \tt(m4) to generate "configure" scripts, that are used +for configuring \link(http://www.gnu.org/, GNU) software for a +particular platform.) + +\p(Htm4l is a set of macros for generating HTML. Html4 is written by +Terry Jones (terry@cliffs.ucsd.edu). See +\showlink(http://cliffs.ucsd.edu/terry/htm4l/htm4l/main.html) for +details. ) + +\p(Various programs uses m4 to preprocess configuration files, for +example the X11 window manager fvwm.) + +\p( There is an \link(http://www.ssc.com/lg/issue22/using_m4.html, +article in the Linux Gazette) about writing HTML with GNU m4 written by +\link(mailto:bhepple@bit.net.au, Bob Hepple) . More recent versions +are kept at \link(http://www.bit.net.au/~bhepple, Bob's home site). +The macros are used to maintain a large commercial site at +\showlink(http://www.finder.com.au).) + + +\p(\link(thissite.htm, These files are created with GNU m4 \__m4_version__).) + + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/visions.m4 b/examples/WWW/m4lib/visions.m4 new file mode 100644 index 00000000..c904976d --- /dev/null +++ b/examples/WWW/m4lib/visions.m4 @@ -0,0 +1,28 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([The Road Ahead]) + +\divert(1) +\h2([Possible features for future versions]) + + +\ul( + +\li \p(Guile can be used as an extension language so complicated macros can be +written in Scheme while still maintaining the m4 interface.) + +\li\p(A kind of super-quotes can be added, quotes that aren't stripped +when read, as are normal quotes. These quotes should be stripped when +output. In that way text can be super-quote and consequently passed +untouched to the output. It is a bit like comments, but there the +quotes are removed before output.) + +) + +\p(See also the \link(todo.htm, TODO) file.) + + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/m4lib/whatis.m4 b/examples/WWW/m4lib/whatis.m4 new file mode 100644 index 00000000..506269a2 --- /dev/null +++ b/examples/WWW/m4lib/whatis.m4 @@ -0,0 +1,43 @@ +include(`setup.m4') + +\set_author([René Seindal]) +\set_title([What is GNU m4]) + +\divert(1) + +\p([GNU \tt(m4) is an implementation of the traditional Unix macro +processor. It is mostly SVR4 compatible, although it has some extensions +(for example, handling more than 9 positional parameters to macros). GNU +\tt(m4) also has built-in functions for including files, running shell +commands, doing arithmetic, etc.]) + +\p([GNU \tt(m4) is a macro processor, in the sense that it copies its +input to the output, expanding macros as it goes. Macros are either +builtin or user-defined, and can take any number of arguments. Besides +just doing macro expansion, m4 has builtin functions for including named +files, running UNIX commands, doing integer arithmetic, manipulating +text in various ways, recursion, etc... m4 can be used either as a +front-end to a compiler, or as a macro processor in its own right.]) + +\p([The m4 macro processor is widely available on all UNIXes. Usually, +only a small percentage of users are aware of its existence. However, +those who do often become commited users. The growing popularity of GNU +Autoconf, which prerequires GNU m4 for generating the `configure' +scripts, is an incentive for many to install it, while these people will +not themselves program in m4. GNU m4 is mostly compatible with the +System V, Release 3 version, except for some minor differences.]) + +\p([Some people found m4 to be fairly addictive. They first use m4 for +simple problems, then take bigger and bigger challenges, learning how to +write complex m4 sets of macros along the way. Once really addicted, +users pursue writing of sophisticated m4 applications even to solve +simple problems, devoting more time debugging their m4 scripts than +doing real work. Beware that m4 may be dangerous for the health of +compulsive programmers.]) + +\p([Autoconf needs GNU m4 for generating `configure' scripts, but not for +running them.]) + +\divert(0)\dnl +\DO_LAYOUT([\undivert(1)]) +\divert(-1) diff --git a/examples/WWW/modules.htm b/examples/WWW/modules.htm new file mode 100644 index 00000000..ee668972 --- /dev/null +++ b/examples/WWW/modules.htm @@ -0,0 +1,347 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Modules</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Modules</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<PRE>This directory contains demonstration modules for GNU m4. + +Nothing in this directory is built by default. + +Dynamic modules is a experimental feature of GNU m4. Currently it has +only been certified to work under Linux 2.0. + +Dynamic modules are only available if GNU m4 was configured with +--with-modules and if the dlopen(3) interface is available in the +operating system. + +Implementation details are in ../src/module.c + +A module is a compiled shared object, i.e., modules are written in C and +then compiled. The compiled file can then be loaded into a running m4 +process by calling the builtin "loadmodule". This will give GNU m4 +access to any system feature with a C interface. + +Modules are searched for in M4MODPATH, if set, and in a module directory +defined at configure time, default /usr/local/libexec/m4. + +A module extends GNU m4 by defining new builtins, It can define builtins +with the same names as existing builtins, which will then be +unavailable. A module cannot redefine internal functions of GNU m4, +such as the input parser or argument handling. + +The infrastructure for writing and compiling modules is still a bit +wanting. + +Each module should include the two header files ../src/m4.h and +../src/builtin.h. These will include <ctype.h>, <stdio.h>, +../lib/obstack.h and ../config.h. + +Each module *must* define the symbol "m4_macro_table" as a pointer to a +table of "struct builtin" (defined in m4.h). The table ends with an +entry with name == NULL. The builtins described in the table will be +defined by GNU m4 as were they normal builtins. + +If a module defines the symbol "m4_init_module", it is supposed to be a +function with a prototype of "void m4_init_module(struct obstack *obs)", +and it will be called as soon as the module is loaded. Any non-finished +object left on the obstack will be the expansion of the call of the +builtin "loadmodule". The obstack pointer might be NULL (in the future). + +If a module defines the symbol "m4_finish_module", it is supposed to be +a function with a prototype of "void m4_finish_module(void)", and it +will be called just before GNU m4 exits. This will allow a module to +clean up before exit. There is no way of communicating information to +the user, as GNU m4 exits immeidately afterwards. + +No other symbols will be used by GNU m4. Other external symbols within +the module are private and will not be accessible to GNU m4 or to other +modules. + +Modules are allowed to call external functions already defined within +the GNU m4 sources. Some of these have prototypes in builtin.h. + + +A complete, though silly, example is found in test.c. A more +interesting example is in time.c. + +To try the demos, compile with `make' and run them with the commands as: + + M4MODPATH=`pwd` ../src/m4 time.m4 + + +</PRE> + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/news.htm b/examples/WWW/news.htm new file mode 100644 index 00000000..ed4f374f --- /dev/null +++ b/examples/WWW/news.htm @@ -0,0 +1,551 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - NEWS - History of user-visible changes</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>NEWS - History of user-visible changes</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<PRE>GNU m4 NEWS - History of user-visible changes. -*-indented-text-*- +Copyright (C) 1992, 1993, 1994, 1998 Free Software Foundation, Inc. + +Version beta 1.4m - November 1998, by Rene' Seindal + +* Using libtool for compiling modules and for linking main app. + +* Reorganised the dynamic module code to encapsulate system dependencies + better. The code for HPUX shl_load() still needs testing and debugging. + A dld interface is also missing. Any volunteers? + +* The files from the GNU m4 web-site is now in examples/WWW as a more + complete example of what GNU m4 can do. + +Version beta 1.4l - November 1998, by Rene' Seindal + +* GNU m4 now has an escape syntax category. If a character is marked as + an escape, words are only recognised as macros if preceded by an escape + character. It is a bit like -P, but dynamic: it can be turned on and + off. The GNU m4 web-site on http://www.seindal.dk/rene/gnu/ is + maintained with this feature - the m4 source is available on the site. + +* The module interface is improved, thanks to "Brian J. Fox" + <bfox@datawave.net>, who have contributed some code from Meta-HTML. The + modules now build automatically and installs properly, by default in + /usr/local/libexec/m4. There is a preliminary, untested support for + shl_load(). + +* There is now a __m4_version__ macro that expands to the current version + number. + +Version beta 1.4k - November 1998, by Erick Branderhorst and Rene' Seindal + +* GNU m4 now uses gettext to support internationalization. + +* GNU m4 now uses automake to control Makefile.in generation. This + should make it more consistent with the GNU standards. + +* GNU m4 will use the gmp library for multiple precision integral and + rational arithmetic in `eval' if configured with `--with-gmp'. If + configured without `--with-gmp' or if gmp is not available, and the type + `long long int' is, GNU m4 will use that for `eval' arithmetic. + +* GNU m4 now parses the input according to a syntax table, that can be + modified through the new builtin `changesyntax'. It is a generalisation + of the existing builtins `changecom' and `changequote'. The changes are + completely backwards compatible (except for the existence of + `changesyntax'). + +* Sync lines can be turned on and off with the `syncoutput' builtin. The + builtin `syncoutput' is a GNU extension. + +* New experimental feature: dynamically loadable modules. New builtin + `loadmodules' loads shared libraries, that can define new builtin + macros, ie, new macros can be written in C. Depends on the dlopen() + interface, and is currently only tested on Linux. Enabled at configure + time with `--with-modules'. Documentation is in src/module.c and + module/README. + +* Implement a GNU message catalog for French (Franc,ois Pinard). + +* Filenames found through path searches are now correctly reflected in + error and debug messages and through the `__file__' macro. + +Bugs fixed + +* All 8-bit characters can now be used for quotes. + + +Version 1.4 - October 1994, by Franc,ois Pinard + +(No user visible changes) + + +Version 1.3 - September 1994, by Franc,ois Pinard + +* Diversions are created as needed. Option `-N' is still accepted, but +otherwise ignored. Users should use only negative diversion numbers, +instead of high positive numbers, for diverting to nowhere. + +* Diversions should also work faster. No temporary files will be needed +at all if all diversions taken altogether do not use more than 512K. + +* Frozen state files may be produced with the `--freeze-state' (-F) +option and later brought back through the `--reload-state' (-R) option. + + +Version 1.2 - July 1994, by Franc,ois Pinard + +* In patsubst(STRING, REGEXP, REPLACEMENT), \& in REPLACEMENT has been +changed to represent this part of STRING matched by the whole REGEXP, +instead of the whole STRING as before. \0 does the same, but emits a +diagnostic saying it will disappear in some subsequent release. + +* eval(EXPR) emits a diagnostic if EXPR has suffixed crumb. The same for +other numeric conversions in incr(), decr(), divert(), etc. + +* `--fatal-warnings' (-E) stops execution at first warning. + +* `--nesting-limit=LEVEL' (-L LEVEL) sets a limit to macro nesting. +It is initially fixed at 250. + +* `--word-regexp=REGEXP' (-W REGEXP) modifies macro name syntax, like +does the new `changeword(REGEXP)' macro. This feature is experimental, +tell me your opinions about it. You do need --enable-changeword at +configure time to get these things. Do *not* depend on them yet. + +* Trace output format is scannable by GNU Emacs' next-error function. + +* Stack overflow is detected and diagnosed on some capable systems. + +* Various bugs have been corrected, m4 should be more portable. See the +ChangeLog for details. + + +Version 1.1 - November 1993, by Franc,ois Pinard + +Changes which might affect existing GNU m4 scripts: + +* Option `-V' has been removed, use `--version' instead. `--version' +writes on standard output instead of standard error, and inhibits any +script execution. + +* `--no-gnu-extensions' has been renamed `--traditional'. + +* In `eval', `^' used to indicate exponentiation, use `**' instead. + +* The automatic undiversion which takes place at end of all input is +forced into the main output stream. + +Changes which are unlikely to affect existing scripts: + +* `--help' prints an usage summary on standard output. Script execution +is then inhibited. + +* `--prefix-builtins' (-P) prefixes all builtin macros by `m4_'. + +* Most builtin macros for which arguments are mandatory, called without +any arguments, are no more recognized as builtin macros: they are +consequently copied verbatim to the output stream. + +* `define' and `pushdef' are usable with only one argument, they give +this argument an empty definition. + +* `eval' new operators for binary representation handling: `^' for +exclusive-or, `~' for the bitwise negation, `<<' and `>>' for shifts. + +* `eval' recognizes the notation 0bDIGITS for binary numbers and the +notation 0rRADIX:DIGITS for numbers in any radix from 1 to 36. + +Version 1.0.3 - December 1992, by Franc,ois Pinard + +Changes for the user: + +* `dnl' outputs a diagnostic if immediately followed by `('. Usually, +`dnl' is followed by newline or whitespace. + +* `ifelse' accepts without complaining the common idiom of having only +one argument. This is useful for introducing long comments. + +* `eval' always expresses values as signed, whatever the radix. + +* M4OPTS environment variable is no longer obeyed. + +* `--no-warnings' option is renamed `--silent'. + +* Debug lines use a new format more compatible with GNU standards. + +* Various bugs have been corrected. See the ChangeLog for details. + +Changes for the installer: + +* GNU m4 now uses an Autoconf-generated configure script, and should be +more easily portable in many ways. (Cray is not supported yet). + +* `make check' has been made more portable, expect no errors. + +Changes for the programmer: + +* Sources have been fully reindented to comply with GNU standards, and +cleaned up in many ways. + +* Sources have been protoized. Non-ANSI compilers are automatically +detected, then sources are unprotoized on the fly before compilation. + +* GNU m4 uses newer versions of obstack, regex, getopt, etc. + +Version 1.0 - October 1991, by Rene' Seindal + +* Uses GNU configure, taken from the gdb distribution. + +* Uses GNU getopt(), with long option names. + +* The -Q/+quiet option is added, which suppresses warnings about missing +or superflous arguments to built-in macros. + +* Added default options via the M4OPTS environment variable. + +* Several minor bugs have been fixed. + +Version 0.99 - July 1991, by Rene' Seindal + +* The builtins `incr' and `decr' are now implemented without use of +`eval'. + +* The builtin `indir' is added, to allow for indirect macro calls +(allows use of "illegal" macro names). + +* The debugging and tracing facilities has been enhanced considerably. +See the manual for details. + +* The -tMACRO option is added, marks MACRO for tracing as soon as it +is defined. + +* Builtins are traced after renaming iff they were before. + +* Named files can now be undiverted. + +* The -Nnum option can be used to increase the number of divertions +available. + +* Calling changecom without arguments now disables all comment handling. + +* A bug in `dnl' is fixed. + +* A bug in the multi-character quoting code is fixed. + +* Several typos in the manual has been corrected. More probably persist. + +Version 0.75 - November 1990, by Rene' Seindal + +* Implemented search path for include files (-I option and M4PATH +environment variable). + +* Implemented builtin `format' for printf-like formatting. + +* Implemented builtin `regexp' for searching for regular expressions. + +* Implemented builtin `patsubst' for substitution with regular +expressions. + +* Implemented builtin `esyscmd', which expands to a shell commands output. + +* Implemented `__file__' and `__line__' for use in error messages. + +* Implemented character ranges in `translit'. + +* Implemented control over debugging output. + +* Implemented multi-character quotes. + +* Implemented multi-character comment delimiters. + +* Changed predefined macro `gnu' to `__gnu__'. + +* Changed predefined macro `unix' to `__unix__', when the -G option is +not used. With -G, `unix' is still defined. + +* Added program name to error messages. + +* Fixed two missing null bytes bugs. + +Version 0.50 - January 1990, by Rene' Seindal + +* Initial beta release. + +Local Variables: +fill-column: 75 +End: + +</PRE> + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/readme.htm b/examples/WWW/readme.htm new file mode 100644 index 00000000..09d483e7 --- /dev/null +++ b/examples/WWW/readme.htm @@ -0,0 +1,329 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - README</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>README</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<PRE>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 built-in 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' has been originally written by René Seindal, from Denmark. + +If GNU `m4' is meant to serve GNU `autoconf', beware that `m4' +should be fully installed *prior to* configuring `autoconf' itself. + +In the subdirectories `tests' and `examples' you will find various m4 +files, ranging from trivial test files to rather advanced macros. If +you intend to use m4 seriously, you might find useful material down +there. + +See file `COPYING' for copying conditions. +See file `INSTALL' for compilation and installation instructions. +See file `ABOUT-NLS' for how to customize this program to your language. +See file `NEWS' for a list of major changes in the current release. +See file `THANKS' for a list of contributors. + +By using `./configure --with-gmp, you get multiple precision integral +and rational arithmetic in eval. The implementation depends on the GNU +gmp v2 library. + +By using `./configure --with-modules, you get the possibility of using +dynamic modules. The implementation depends on dlopen(3) interface. +See file `modules/README' for a more detailed description. + +By using `./configure --enable-changeword', you get an experimental +feature which allows for changing the syntax of what is a "word" in +`m4'. THIS WILL PROBABLY GO AWAY, so don't count on it. Some of the +same things can be achieved with `changesyntax' at a much better speed. + +By using `./configure --with-dmalloc', GNU m4 is linked with Gray +Watson's dmalloc package. It is a debugging option for finding memory +management problems. Gray Watson's dmalloc package is available at +ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz. + +Send bug reports, comments or ideas to `bug-m4@gnu.org'. A bug report +is an adequate description of the problem: your input, what you +expected, what you got, and why this is wrong. Diffs are welcome, but +they only describe a solution, from which the problem might be uneasy to +infer. Don't forget all relevant information about your operating +system, compiler, libraries, ... + +</PRE> + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/thanks.htm b/examples/WWW/thanks.htm new file mode 100644 index 00000000..78470a16 --- /dev/null +++ b/examples/WWW/thanks.htm @@ -0,0 +1,377 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - People who have contributed to m4</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>People who have contributed to m4</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<PRE>GNU m4 THANKS file + +GNU m4 has originally been written by Rene' Seindal. Many people +further contributed to GNU m4 by reporting problems, suggesting +various improvements or submitting actual code. Here is a list of +these people. Help me keep it complete and exempt of errors. + + + +Akiko Matsushita matusita@sra.co.jp +Alan Magnuson awm@osc.edu +Alexander Lehmann alex@hal.rhein-main.de +Amos Shapira amoss@cs.huji.ac.il +Andreas Gustafsson gson@niksula.hut.fi +Andreas Schwab schwab@ls5.informatik.uni-dortmund.de +Andrew Athan athan@morgan.com +Andrew Bettison andrewb@zip.com.au +Assar Westerlund assar@nada.kth.se +Ben A. Mesander ben@piglet.cr.usgs.gov +Ben Elliston bje@cygnus.com +Bengt Mertensson bengt@mathematik.uni-bremen.de +Bernhard Daeubler daeb@physik.uni-ulm.de +Bill Bumgarner bbum@thoughtport.com +Bjorn R. Bjornsson brb@falcon.is +Brendan Kehoe brendan@cygnus.com +Brian J. Fox bfox@datawave.net +Brian D. Carlstrom bdc@clark.lcs.mit.edu +David J. MacKenzie djm@uunet.uu.net +Erez Zadok ezk@cs.columbia.edu +Eric Allman eric@cs.berkeley.edu +Eric Backus ericb@lsid.hp.com +Eric Fischer enf1@ellis.uchicago.edu +Erick Branderhorst Erick.Branderhorst@asml.nl +François Pinard pinard@iro.umontreal.ca +Gary Affonso Gary_Affonso@iqinc.com +Geoff Russell grussell@guest.adelaide.edu.au +Greg McGary gkm@cstone.net +Hal Peterson hrp@pecan.cray.com +Hoang Uong hoang@ornews.intel.com +Hongjiu Lu hjl@nynexst.com +Ian Taylor ian@cygnus.com +Jan Djarv Jan.Djarv@sa.erisoft.se +Jason Merrill jason@jarthur.claremont.edu +Jim Avera jima@netcom.com +Jim Kingdom kingdon@cygnus.com +Jim Meyering meyering@na-net.ornl.gov +Joel Sherrill jsherril@uahcs2.cs.uah.edu +John David Anglin dave@hiauly1.hia.nrc.ca +John Gerard Malecki johnm@artisan.com +Joseph E. Sacco jsacco@ssl.com +Joshua R. Poulson jrp@plaza.ds.adp.com +Karl Berry karl@cs.umb.edu +Karl Vogel vogelke@c-17igp.wpafb.af.mil +Kaveh R. Ghazi ghazi@noc.rutgers.edu +Keith Bostic bostic@abyssinian.sleepycat.com +Kristine Lund lund@lpnaxp.in2p3.fr +Krste Asanovic krste@icsi.berkeley.edu +Marcus Daniels marcus@ee.pdx.edu +Marion Hakanson hakanson@cse.ogi.edu +Mark Seiden mis@seiden.com +Massimo Dal Zotto dz@cs.unitn.it +Matthias Rabe rabe@mathematik.uni-bielefeld.de +Michael Fetterman mafetter@ichips.intel.com +Michael L. Welcome welcome@bigbird.llnl.gov +Mike Andrews kramer@fragile.termfrost.org +Mike Howard mike@clove.com +Mike Lijewski lijewski@theory.tc.cornell.edu +Nick S. Kanakakorn skanan@otl.scu.edu +Nicolas Pioch pioch@inf.enst.fr +Noah Friedman friedman@gnu.org +Pete Chown pete.chown@dale.dircon.co.uk +Pierre Gaumond gaumondp@ere.umontreal.ca +Pierre Mathieu mathieu@geod.emr.ca +Rafael Corvalan rafael@club-internet.fr +René Seindal rene@seindal.dk +Richard Ling richard@research.canon.oz.au +Richard Stallman rms@gnu.org +Robert Bernstein rocky@panix.com +Roland H. Pesch roland@wrs.com +Roland McGrath roland@gnu.org +Scott Bartram deneb!scottb +Simon Leinen simon@lia.di.epfl.ch +Skip Montanaro skip@automatrix.com +Stephen Perkins perkins@cps.msu.edu +Steve Williamson willy@uinpla.npl.uiuc.edu +Terry Jones terry@cliffs.ucsd.edu +Thorsten Ohl ohl@physics.harvard.edu +Tom McConnell tmcconne@sedona.intel.com +Tom Quinn trq@dionysos.thphys.ox.ac.uk +Tom Tromey tromey@cns.caltech.edu +Ulrich Drepper drepper@gnu.org +Vern Paxson vern@ee.lbl.gov +Vic Abell abe@cc.purdue.edu +Vivek P. Singhal singhal@cs.utexas.edu +Walter Wong wcw+@cmu.edu + +</PRE> + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/thissite.htm b/examples/WWW/thissite.htm new file mode 100644 index 00000000..03e2a01a --- /dev/null +++ b/examples/WWW/thissite.htm @@ -0,0 +1,327 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - This site</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>This site</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<P> +This GNU m4 site is maintained by René Seindal (<A HREF="mailto:rene@seindal">rene@seindal</A>). +</P> + + +<P> +All files are generated using GNU m4 1.4l. You can view +the <A HREF="m4lib/">source files</A>. They are very simple. They use some +features from Gnu m4 1.4l +</P> + + +<P> +The basic M4 definitions of quotes comments escapes are in +<A HREF="m4lib/setup.m4">m4lib/setup.m4</A>. This is first included by all files to +configure the enviroment correctly for the other files. To avoid have +macros called by accident an escape character is defined with +changesyntax. <I>This is a new feature in m4 1.4l</I>. +</P> + + +<P> +Some fairly general macros to generate various HTML construct are +found in <A HREF="m4lib/html.m4">m4lib/html.m4</A>. There are macros for simple tags containers with and with attributes links and a few utility macros. +</P> + + +<P> +The visual aspects of the pages are in <A HREF="m4lib/layout.m4">m4lib/layout.m4</A>. +The macros herein generate the complete HTML structure for the pages. +There are macros for making the header and the body of the document. +</P> + + +<P> +The page body is passed to the layout definitions as an argument. As +the text can be large it is first diverted and the text passed to the +layout macros is simply a call to undivert. That way a very large text +can be passed around with very little cost. This page is made with +<A HREF="m4lib/thissite.m4">these definitions</A>. +</P> + + +<P> +There is a single file for each HTML file. +</P> + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/todo.htm b/examples/WWW/todo.htm new file mode 100644 index 00000000..9c5100f1 --- /dev/null +++ b/examples/WWW/todo.htm @@ -0,0 +1,388 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - TODO - Things still to be done</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>TODO - Things still to be done</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<PRE>* TODO file for GNU m4 -*- indented-text -*- + +Tell the maintainers at <bug-m4@gnu.org> if you feel like volunteering +for any of these ideas or if you have others to add. + + +* Features or problems + + + GMP eval() should be enables if the library is present, maybe by + providing two different versions of eval(). That way users can + choose whether to use gmp on an individual basis. + + + There should be a way ot have m4 discard comments instead of + outputting them. + + + Implement discarding comment delimiters with the syntax table. + + + The module system is still rudimentary (see below) + + + Changes in the syntax_table are not saved to frozen files. + + + Information about loaded modules is not saved to frozen files. + + + m4wrap.1.test fail on Solaris 2.6 using egcs 1.1a compiler (Erick B). + + + The $ used in user defined macros cannot be changed through + changesyntax. It should be handled as a modifier. + + + Make show include dependencies like gcc so targets are updated + when their (included) input files are updated (Erick B). + + + The test case `other-tests/stackovf.test' does not work. + + + Sort out all the weird forms of interaction between changesyntax, + changecom and changequote. What happens if you install a quote with + changequote and removes it with changesyntax and vice versa. + + + Add support for wide character sets. + + +* Optimization and clean up + + + Have NULs go really undisturbed through GNU m4 + GNU m4 is lousy regarding NULs in streams (this would require + maintaining the string lengths, and avoiding strlen, strcpy, + etc.). + + +* Module specific issues + + + Support for other DL interfaces besides dlopen, such as dld and + hpux is still missing. + + + Modules should be loadable from the command line with something like + `-M module.so' o `--load-module=module.so'. M4 should abort if it + fails. + + + Some way of linking a module statically is needed, for systems + without support for dynamic loading. + + + +Below is the old 1.4 TODO list, several years old. Only a few points +have been kept. Some things are fixed, many others just seem +dated. Write me if I have been to harsh. (René Seindal) + +------------------------------------------------------------------------ +Tell <pinard@iro.umontreal.ca> if you feel like volunteering for any +of these ideas, listed more or less in decreasing order of priority. +Some TODO items are implicit from received email. See file BACKLOG. + +.* Features or problems +. + Update documentation from accumulated mail about it +. + Changeword without arguments should restore default behavior +. + Study synclines at the very beginning of each diverted sequence +. + Make eval work on bignums - the 32 bits limit is artificial + From Krste Asanovic <krste@icsi.berkeley.edu>, 1993-03-20 +. + Make show include dependencies like gcc so targets are updated + when their (included) input files are updated (Erick B). +. + Ask FSF to create m4-bugs@gnu.org for bug reports (Erick B). +. + m4wrap.1.test fail on Solaris 2.6 using egcs 1.1a compiler (Erick B). + +.* Optimization and clean up +. + Check for memory leaks and uninitialized reads + From Vern Paxson <vern@horse.ee.lbl.gov> on 1993-12-06 +. + Simplify format/ecvt code, together with HAVE_EFGCVT +. + Finalize the stdarg vs varargs thing +. + Profile GNU m4 and speed it up + From David J. MacKenzie <djm@eng.umd.edu>, 1993-01-20 + + GNU m4 should be sped up by a factor of three for competing + with other versions (I think that the lexer is not agressive + enough and too often return single characters; obstacks might + be a little abused, too). +. + Have NULs go really undisturbed through GNU m4 + See `dumpdef' and debugging section, which abuses %s + From Thorsten Ohl <ohl@chico.harvard.edu>, 1992-12-21 + + path.c (add_include_directory): Why the '\0' terminator? + + GNU m4 is lousy regarding NULs in streams (this would require + maintaining the string lengths, and avoiding strlen, strcpy, + etc.). +. + Clean up the obstack.[ch] code +. + Use rx.[ch] instead of regex.[ch] + From Hal Peterson <hrp@ironwood.cray.com>, 1994-04-22 + +</PRE> + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/uses.htm b/examples/WWW/uses.htm new file mode 100644 index 00000000..9988dacf --- /dev/null +++ b/examples/WWW/uses.htm @@ -0,0 +1,322 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - Current uses of m4</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>Current uses of m4</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<P> +The MTA sendmail uses <TT>m4</TT> for generating configuration files. +</P> + + +<P> +<A HREF="http://www.gnu.org/software/autoconf/autoconf.html">GNU +Autoconf</A> uses <TT>m4</TT> to generate "configure" scripts that are used +for configuring <A HREF="http://www.gnu.org/">GNU</A> software for a +particular platform. +</P> + + +<P> +Htm4l is a set of macros for generating HTML. Html4 is written by +Terry Jones (terry@cliffs.ucsd.edu). See +<A HREF="http://cliffs.ucsd.edu/terry/htm4l/htm4l/main.html">http://cliffs.ucsd.edu/terry/htm4l/htm4l/main.html</A> for +details. +</P> + + +<P> +Various programs uses m4 to preprocess configuration files for +example the X11 window manager fvwm. +</P> + + +<P> +There is an <A HREF="http://www.ssc.com/lg/issue22/using_m4.html">article in the Linux Gazette</A> about writing HTML with GNU m4 written by +<A HREF="mailto:bhepple@bit.net.au">Bob Hepple</A> . More recent versions +are kept at <A HREF="http://www.bit.net.au/~bhepple">Bob's home site</A>. +The macros are used to maintain a large commercial site at +<A HREF="http://www.finder.com.au">http://www.finder.com.au</A>. +</P> + + + +<P> +<A HREF="thissite.htm">These files are created with GNU m4 1.4l</A>. +</P> + + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/visions.htm b/examples/WWW/visions.htm new file mode 100644 index 00000000..eceec6f7 --- /dev/null +++ b/examples/WWW/visions.htm @@ -0,0 +1,309 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - The Road Ahead</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>The Road Ahead</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<H2>Possible features for future versions</H2> + + + +<UL> +<LI> <P> +Guile can be used as an extension language so complicated macros can be +written in Scheme while still maintaining the m4 interface. +</P> + + +<LI><P> +A kind of super-quotes can be added quotes that aren't stripped +when read as are normal quotes. These quotes should be stripped when +output. In that way text can be super-quote and consequently passed +untouched to the output. It is a bit like comments but there the +quotes are removed before output. +</P> + + + +</UL> + + +<P> +See also the <A HREF="todo.htm">TODO</A> file. +</P> + + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/WWW/whatis.htm b/examples/WWW/whatis.htm new file mode 100644 index 00000000..3f793cd0 --- /dev/null +++ b/examples/WWW/whatis.htm @@ -0,0 +1,327 @@ +<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN"> +<HTML> +<HEAD> +<TITLE>GNU m4 - What is GNU m4</TITLE> +<META NAME="AUTHOR" CONTENT="René Seindal"> +<META NAME="GENERATOR" CONTENT="GNU m4 1.4l"> +</HEAD> + <BODY text="#000000" bgcolor="#FFCC99" link="#0000EF" alink="#FF0000" vlink="#51188E"> +<TABLE cellpadding=5 width="100%"> +<TR align=left valign=bottom> +<TD align=center valign=center colspan="3" width="100%" bgcolor="#FF9900"> + +<H1>GNU m4</H1> + +<H2>What is GNU m4</H2> + +</TD> + +</TR> + <TR > +<TD align=left valign=top width="15%" bgcolor="#FF9900"> + + + +<TABLE align=left valign=top columns=1> +<TR> +<TD bgcolor="#CC6600"> +<P> +<B>Generel info</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="whatis.htm">What is m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="features.htm">Features</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="uses.htm">Uses of m4</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Documentation</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="man/m4_toc.html">Manual</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Source files</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="readme.htm">README</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="todo.htm">TODO</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="news.htm">NEWS</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="changelog.htm">ChangeLog</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thanks.htm">Contributors</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="m4/">Browse it</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>The Future</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="modules.htm">Modules</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="visions.htm">Visions</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Development</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="lists.htm">Mailing-lists</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="feedback.htm">Feedback</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="download.htm">Download</A></B> +</P> +</FONT> + +</TD> + +</TR> + <TR> +<TD bgcolor="#CC6600"> +<P> +<B>Examples</B> +</P> + +</TD> + +</TR> + <TR> +<TD> + +<FONT size=-1><P> +<B><A HREF="thissite.htm">This site</A></B> +</P> +</FONT> + +</TD> + +</TR> + +</TABLE> + + + + + +</TD> + <TD align=left valign=top width="90%"> + + +<P> +GNU <TT>m4</TT> 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). GNU +<TT>m4</TT> also has built-in functions for including files, running shell +commands, doing arithmetic, etc. +</P> + + +<P> +GNU <TT>m4</TT> is a macro processor, in the sense that it copies its +input to the output, expanding macros as it goes. Macros are either +builtin or user-defined, and can take any number of arguments. Besides +just doing macro expansion, m4 has builtin functions for including named +files, running UNIX commands, doing integer arithmetic, manipulating +text in various ways, recursion, etc... m4 can be used either as a +front-end to a compiler, or as a macro processor in its own right. +</P> + + +<P> +The m4 macro processor is widely available on all UNIXes. Usually, +only a small percentage of users are aware of its existence. However, +those who do often become commited users. The growing popularity of GNU +Autoconf, which prerequires GNU m4 for generating the `configure' +scripts, is an incentive for many to install it, while these people will +not themselves program in m4. GNU m4 is mostly compatible with the +System V, Release 3 version, except for some minor differences. +</P> + + +<P> +Some people found m4 to be fairly addictive. They first use m4 for +simple problems, then take bigger and bigger challenges, learning how to +write complex m4 sets of macros along the way. Once really addicted, +users pursue writing of sophisticated m4 applications even to solve +simple problems, devoting more time debugging their m4 scripts than +doing real work. Beware that m4 may be dangerous for the health of +compulsive programmers. +</P> + + +<P> +Autoconf needs GNU m4 for generating `configure' scripts, but not for +running them. +</P> + + + +</TD> + +</TR> + +</TABLE> + +</BODY> + + +</HTML> + + diff --git a/examples/capitalize.m4 b/examples/capitalize.m4 new file mode 100644 index 00000000..5c28de22 --- /dev/null +++ b/examples/capitalize.m4 @@ -0,0 +1,8 @@ +dnl +dnl convert to upper- resp. lowercase +define(`upcase', `translit(`$*', `a-z', `A-Z')') +define(`downcase', `translit(`$*', `A-Z', `a-z')') +dnl +dnl capitalize a single word +define(`capitalize1', `regexp(`$1', `^\(\w\)\(\w*\)', `upcase(`\1')`'downcase(`\2')')') +define(`capitalize', `patsubst(`$1', `\w+', ``'capitalize1(`\0')')') diff --git a/examples/capitalize.test b/examples/capitalize.test new file mode 100755 index 00000000..5b80f5c0 --- /dev/null +++ b/examples/capitalize.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# capitalize.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/capitalize.m4 >in + +cat <<\EOF >ok + + +CONVERT TO UPPER CASE +convert to lower case + + +This Sentence Should Be Capitalized +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/comments.m4 b/examples/comments.m4 new file mode 100644 index 00000000..c1e3be0a --- /dev/null +++ b/examples/comments.m4 @@ -0,0 +1,7 @@ +# An ordinary comment +define(`foo', # A comment in a macro +`Macro `foo' expansion') +foo +define(`comment', `*** Macro `comment' expansion ***') +changecom(`@', `@') +foo diff --git a/examples/comments.test b/examples/comments.test new file mode 100755 index 00000000..63161dc2 --- /dev/null +++ b/examples/comments.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# comments.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(comments.m4)dnl +EOF + +cat <<\EOF >ok +# An ordinary comment + +# A comment in a macro +Macro foo expansion + + +# A *** Macro comment expansion *** in a macro +Macro foo expansion +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok diff --git a/examples/ddivert.m4 b/examples/ddivert.m4 new file mode 100644 index 00000000..e6e0017e --- /dev/null +++ b/examples/ddivert.m4 @@ -0,0 +1,4 @@ +divert(1)Text diverted a first time. +divert(0)undivert(1)dnl +divert(1)Text diverted a second time. +divert(0)undivert(1)dnl diff --git a/examples/ddivert.test b/examples/ddivert.test new file mode 100755 index 00000000..5db82e90 --- /dev/null +++ b/examples/ddivert.test @@ -0,0 +1,18 @@ +#!/bin/sh + +# ddivert.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(ddivert.m4)dnl +EOF + +cat <<\EOF >ok +Text diverted a first time. +Text diverted a second time. +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok diff --git a/examples/debug.m4 b/examples/debug.m4 new file mode 100644 index 00000000..16f4c74e --- /dev/null +++ b/examples/debug.m4 @@ -0,0 +1,4 @@ +define(`countdown', `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')') +debugmode(`aeqc') +traceon(`countdown') +countdown(2) diff --git a/examples/debug.test b/examples/debug.test new file mode 100755 index 00000000..0260641e --- /dev/null +++ b/examples/debug.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# debug.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(debug.m4)dnl +EOF + +cat <<\EOF >ok + + + +2 1 0 Liftoff +EOF + +cat <<\EOF >okerr +m4trace: -1- countdown ... +m4trace: -1- countdown(`2') -> ??? +m4trace: -1- countdown(...) -> `2 ifelse(eval(2 > 0), 1, `countdown(decr(2))', `Liftoff')' +m4trace: -1- countdown ... +m4trace: -1- countdown(`1') -> ??? +m4trace: -1- countdown(...) -> `1 ifelse(eval(1 > 0), 1, `countdown(decr(1))', `Liftoff')' +m4trace: -1- countdown ... +m4trace: -1- countdown(`0') -> ??? +m4trace: -1- countdown(...) -> `0 ifelse(eval(0 > 0), 1, `countdown(decr(0))', `Liftoff')' +EOF + +M4PATH=$srcdir $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/defs b/examples/defs new file mode 100644 index 00000000..cf97e3b3 --- /dev/null +++ b/examples/defs @@ -0,0 +1,54 @@ +# -*- ksh -*- +# Defines for GNU m4 testing environment. +# Erick Branderhorst <Erick.Branderhorst@asml.nl> + +# Ensure $srcdir set correctly. +test -f ${srcdir}/defs || { + echo "defs: installation error" 1>&2 + exit 1 +} + +# If srcdir is relative, we need to modify it. +case "$srcdir" in + /*) + ;; + + *) + srcdir="../$srcdir" + ;; +esac + +rm -rf testSubDir > /dev/null 2>&1 +mkdir testSubDir +cd testSubDir + +# Build appropriate environment in test directory. Eg create +# configure.in, touch all necessary files, etc. + +# nothing yet + +# See how redirections should work. User can set VERBOSE to see all +# output. +test -z "$VERBOSE" && { + exec > /dev/null 2>&1 +} + +# User can set MAKE to choose which make to use. Must use GNU make. +test -z "$MAKE" && MAKE=make + +echo "=== Running test $0" + +# See how GNU m4 should be run. No options as default. +test -z "$M4" && M4=../../src/m4 + +# See how cmp should be run. +test -z "$CMP" && CMP=cmp + +# Setting nls related vars. Override them in the test when needed. +LANGUAGE=C +export LANGUAGE +LC_ALL=C +export LC_ALL +LANG=C +export LANG + diff --git a/examples/esyscmd.m4 b/examples/esyscmd.m4 new file mode 100644 index 00000000..b839148c --- /dev/null +++ b/examples/esyscmd.m4 @@ -0,0 +1,5 @@ +define(`hostname', esyscmd(`hostname'))dnl +`hostname = >>'hostname`<<' +define(`hostname', +pushdef(`_tmp', `$1')_tmp(translit(esyscmd(`hostname'), `.', `,'))`'popdef(`_tmp'))dnl +`hostname = >>'hostname`<<' diff --git a/examples/esyscmd.test b/examples/esyscmd.test new file mode 100755 index 00000000..47602094 --- /dev/null +++ b/examples/esyscmd.test @@ -0,0 +1,18 @@ +#!/bin/sh + +# esyscmd.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/esyscmd.m4 >in + +cat <<\EOF >ok +# Cannot use real hostname program because test would fail +hostname = >>www.gnu.org +<< +hostname = >>www<< +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/exp.m4 b/examples/exp.m4 new file mode 100644 index 00000000..8aef93e9 --- /dev/null +++ b/examples/exp.m4 @@ -0,0 +1 @@ +define(`countdown', `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Done')') diff --git a/examples/exp.test b/examples/exp.test new file mode 100755 index 00000000..443e98c7 --- /dev/null +++ b/examples/exp.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# exp.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/exp.m4 >in + +cat <<\EOF >ok +7 +6 +5 +4 +3 +2 +1 +0 +Done +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/file.m4 b/examples/file.m4 new file mode 100644 index 00000000..e7db5f13 --- /dev/null +++ b/examples/file.m4 @@ -0,0 +1,5 @@ +changequote([[,]])dnl +define([[quoteall]], [[patsubst([[[[$*]]]], [[,[ ]+]], [[,]])]])dnl +define([[group]], quoteall(include([[/etc/group]])))dnl +dnl +group()dnl diff --git a/examples/foreach.m4 b/examples/foreach.m4 new file mode 100644 index 00000000..d5b81866 --- /dev/null +++ b/examples/foreach.m4 @@ -0,0 +1,19 @@ +divert(-1) +# foreach(x, (item_1, item_2, ..., item_n), stmt) +define(`foreach', `pushdef(`$1', `')_foreach(`$1', `$2', `$3')popdef(`$1')') +define(`_arg1', `$1') +define(`_foreach', + `ifelse(`$2', `()', , + `define(`$1', _arg1$2)$3`'_foreach(`$1', (shift$2), `$3')')') +# traceon(`define', `foreach', `_foreach', `ifelse') +divert +foreach(`x', `(foo, bar, foobar)', `Word was: x +') +# Something more complex, from Pierre Gaumond <gaumondp@ere.umontreal.ca>. +define(`case', ` $1) + $2=" -$1";; +')dnl +define(`_cat', `$1$2')dnl +`case' "$1" in +foreach(`x', ((a, vara), (b, varb), (c, varc)), `_cat(`case', x)')dnl +esac diff --git a/examples/foreach.test b/examples/foreach.test new file mode 100755 index 00000000..969e1638 --- /dev/null +++ b/examples/foreach.test @@ -0,0 +1,28 @@ +#!/bin/sh + +# foreach.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/foreach.m4 >in + +cat <<\EOF >ok + +Word was: foo +Word was: bar +Word was: foobar + +# Something more complex, from Pierre Gaumond <gaumondp@ere.umontreal.ca>. +case "$1" in + a) + vara=" -a";; + b) + varb=" -b";; + c) + varc=" -c";; +esac +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/forloop.m4 b/examples/forloop.m4 new file mode 100644 index 00000000..a8bb6bce --- /dev/null +++ b/examples/forloop.m4 @@ -0,0 +1,8 @@ +divert(-1) +# forloop(i, from, to, stmt) + +define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') +define(`_forloop', + `$4`'ifelse($1, `$3', , + `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') +divert diff --git a/examples/forloop.test b/examples/forloop.test new file mode 100755 index 00000000..f2a41e7d --- /dev/null +++ b/examples/forloop.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# forloop.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/forloop.m4 >in + +cat <<\EOF >ok + +2**1 = 2 +2**2 = 4 +2**3 = 8 +2**4 = 16 +2**5 = 32 +2**6 = 64 +2**7 = 128 +2**8 = 256 +2**9 = 512 +2**10 = 1024 + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/fstab.m4 b/examples/fstab.m4 new file mode 100644 index 00000000..dbf538ae --- /dev/null +++ b/examples/fstab.m4 @@ -0,0 +1,7 @@ +define(`concat', `translit(``$*'', ` ')') +define(`fsent', `format(`%-25s %-16s nfs %-16s 0 0', `$1:$2', `$3', concat$4)') + +fsent(freja, /home/gevn, /home/gevn, (rw, soft, bg, grpid)) +fsent(freja, /home/freja, /home/freja, (rw, soft, grpid)) +fsent(rimfaxe, /home/rimfaxe, /home/rimfaxe, (rw, soft, bg)) + diff --git a/examples/fstab.test b/examples/fstab.test new file mode 100755 index 00000000..89fd2c6b --- /dev/null +++ b/examples/fstab.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# fstab.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/fstab.m4 >in + +cat <<\EOF >ok + + + +freja:/home/gevn /home/gevn nfs rw,soft,bg,grpid 0 0 +freja:/home/freja /home/freja nfs rw,soft,grpid 0 0 +rimfaxe:/home/rimfaxe /home/rimfaxe nfs rw,soft,bg 0 0 + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/hanoi.m4 b/examples/hanoi.m4 new file mode 100644 index 00000000..c4a80fc6 --- /dev/null +++ b/examples/hanoi.m4 @@ -0,0 +1,15 @@ +divert(-1) + +# move(from, to) +define(`move', `Move one disk from `$1' to `$2'. +') + +# _hanoi (cnt, from, to, aux) +define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', +`_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')') + +# hanoi (cnt) +define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)') + +# traceon(`move', `_hanoi', `decr') +divert`'dnl diff --git a/examples/hanoi.test b/examples/hanoi.test new file mode 100755 index 00000000..6080d5f6 --- /dev/null +++ b/examples/hanoi.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# hanoi.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/hanoi.m4 >in + +cat <<\EOF >ok + +Move one disk from source to destination. +Move one disk from source to auxilliary. +Move one disk from destination to auxilliary. +Move one disk from source to destination. +Move one disk from auxilliary to source. +Move one disk from auxilliary to destination. +Move one disk from source to destination. + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/incl-test.m4 b/examples/incl-test.m4 new file mode 100644 index 00000000..8b7d223f --- /dev/null +++ b/examples/incl-test.m4 @@ -0,0 +1,2 @@ +`include test file.' +define() diff --git a/examples/include.m4 b/examples/include.m4 new file mode 100644 index 00000000..fb788047 --- /dev/null +++ b/examples/include.m4 @@ -0,0 +1,7 @@ +Beginning. +include(`NOFILE') +Intermidiate +include(`test/incl-test.m4') +After +include(`NOFILE') +very late diff --git a/examples/include.test b/examples/include.test new file mode 100755 index 00000000..5d0b1100 --- /dev/null +++ b/examples/include.test @@ -0,0 +1,28 @@ +#!/bin/sh + +# include.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/include.m4 >in + +cat <<\EOF >ok +Beginning. + +Intermidiate +include test file. + + +After + +very late +EOF + +cat <<\EOF >okerr +in:2: m4: Cannot open NOFILE: No such file or directory +in:6: m4: Cannot open NOFILE: No such file or directory +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/indir.m4 b/examples/indir.m4 new file mode 100644 index 00000000..bc301238 --- /dev/null +++ b/examples/indir.m4 @@ -0,0 +1,10 @@ +define(`%%$$##', `>>>$0<<< cnt $#') + +# indir(`%%$$##', nonsens, nonsens) +indir(`%%$$##', nonsens, nonsens) + +# indir(`indir', `%%$$##', nonsens) +indir(`indir', `%%$$##', nonsens) + +# indir(`indir', `indir', `indir', `indir', `%%$$##') +indir(`indir', `indir', `indir', `indir', `%%$$##') diff --git a/examples/indir.test b/examples/indir.test new file mode 100755 index 00000000..e243f97c --- /dev/null +++ b/examples/indir.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# indir.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/indir.m4 >in + +cat <<\EOF >ok + + +# indir(`%%$$##', nonsens, nonsens) +>>>%%$$##<<< cnt 2 + +# indir(`indir', `%%$$##', nonsens) +>>>%%$$##<<< cnt 1 + +# indir(`indir', `indir', `indir', `indir', `%%$$##') +>>>%%$$##<<< cnt 0 +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/iso8859.m4 b/examples/iso8859.m4 Binary files differnew file mode 100644 index 00000000..4ac1d196 --- /dev/null +++ b/examples/iso8859.m4 diff --git a/examples/iso8859.test b/examples/iso8859.test new file mode 100755 index 00000000..3cca92e1 --- /dev/null +++ b/examples/iso8859.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# iso8859.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(iso8859.m4)dnl +EOF + +cat <<\EOF >ok +# Texting quotes +DEFINE +CHANGEQUOTE(«,») +0 TEST # TEST +1 test # test +2 «test» # «test» +3 ««test»» # ««test»» +CHANGEQUOTE(«««,»»») +0 TEST # TEST +1 «TEST» # «TEST» +2 ««TEST»» # ««TEST»» +3 test # test +# Test use of all iso8859 characters except NUL ` ' +Length of string is: 253 +Comparing strings: MATCH +# NUL does not pass through +This will be seen. +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok diff --git a/examples/misc.m4 b/examples/misc.m4 new file mode 100644 index 00000000..eff8766d --- /dev/null +++ b/examples/misc.m4 @@ -0,0 +1,9 @@ +divert(-1) +define(`HOST', `vale') +define(`TMP', maketemp(`/tmp/hejXXXXXX')) +syscmd(`ypmatch' HOST `hosts | awk "{print \$1}"' > TMP) +define(`IP', include(TMP)) +syscmd(`rm -f' TMP) +divert + +IP diff --git a/examples/misc.test b/examples/misc.test new file mode 100755 index 00000000..59ea58ad --- /dev/null +++ b/examples/misc.test @@ -0,0 +1,17 @@ +#!/bin/sh + +# misc.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/misc.m4 >in + +cat <<\EOF >ok + +127.0.0.1 + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/mktests.sh b/examples/mktests.sh new file mode 100644 index 00000000..1546b568 --- /dev/null +++ b/examples/mktests.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +: ${M4:=../../src/m4} + +test $# -eq 1 || exit 1 +FILE=`basename $1 .m4` + + +test -r $FILE.m4 || exit 1 + +if head -1 $FILE.m4 | fgrep -w 'dnl noauto' >/dev/null; then + echo "$FILE.test cannot be generated" 1>&2 + exit 1 +fi + +test -d testSubDir || mkdir testSubDir + +cat "$FILE.m4" > testSubDir/in +(cd testSubDir; $M4 -I.. -d "in" >out 2>err) + +( + +cat <<EOFEOF +#!/bin/sh + +# $FILE.test is part of the GNU m4 testsuite + +. \${srcdir}/defs + +cat \${srcdir}/$FILE.m4 >in +EOFEOF + +echo +echo 'cat <<\EOF >ok' +cat testSubDir/out +echo EOF + +if [ -s testSubDir/err ]; then + echo + echo 'cat <<\EOF >okerr' + sed -e "s, $M4:, m4:," testSubDir/err + echo EOF +fi + +echo +echo 'M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err' +echo 'sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err' + +if [ -s testSubDir/err ]; then + echo '$CMP -s out ok && $CMP -s err okerr' +else + echo '$CMP -s out ok' +fi +) >$FILE.test.new + +if cmp -s $FILE.test.new $FILE.test; then + echo "$FILE.test unchanged" 1>&2 + rm -f $FILE.test.new +else + echo "creating $FILE.test" 1>&2 + mv $FILE.test.new $FILE.test + chmod +x $FILE.test +fi + +rm -f testSubDir/out testSubDir/err diff --git a/examples/multiquotes.m4 b/examples/multiquotes.m4 new file mode 100644 index 00000000..b56cfbd8 --- /dev/null +++ b/examples/multiquotes.m4 @@ -0,0 +1,17 @@ +traceon +changequote([,])dnl +changequote([``], [''])dnl +````traceon'''' +define(``foo'', ````FOO'''')dnl +dumpdef(``foo'')dnl +changequote(``!'', ``!'')dnl +!foo! +foo +dumpdef(!foo!)dnl +define(!bar!, !BAR!) +bar +changequote(!>*>*>*>*>!, !<*<*<*<*<!)dnl five of each +>*>*>*>*>foo bar<*<*<*<*< +foo bar +>*>*>*>*>*>*><*<*<*<*<*<*< +dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)dnl diff --git a/examples/multiquotes.test b/examples/multiquotes.test new file mode 100755 index 00000000..81bd10d1 --- /dev/null +++ b/examples/multiquotes.test @@ -0,0 +1,47 @@ +#!/bin/sh + +# multiquotes.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/multiquotes.m4 >in + +cat <<\EOF >ok + +``traceon'' +foo +``FOO'' + +BAR +foo bar +``FOO'' BAR +*>*>*<*< +EOF + +cat <<\EOF >okerr +m4trace: -1- changequote(`[', `]') +m4trace: -1- dnl +m4trace: -1- changequote([``], ['']) +m4trace: -1- dnl +m4trace: -1- define(``foo'', ````FOO'''') +m4trace: -1- dnl +foo: ````FOO'''' +m4trace: -1- dumpdef(``foo'') +m4trace: -1- dnl +m4trace: -1- changequote(``!'', ``!'') +m4trace: -1- dnl +foo: !``FOO''! +m4trace: -1- dumpdef(!foo!) +m4trace: -1- dnl +m4trace: -1- define(!bar!, !BAR!) +m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<*<!) +m4trace: -1- dnl +bar: >*>*>*>*>BAR<*<*<*<*< +foo: >*>*>*>*>``FOO''<*<*<*<*< +m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<) +m4trace: -1- dnl +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/patsubst.m4 b/examples/patsubst.m4 new file mode 100644 index 00000000..3b390ae0 --- /dev/null +++ b/examples/patsubst.m4 @@ -0,0 +1,8 @@ +# traceon(`patsubst') +patsubst(`GNUs not Unix', `^', `OBS: ') +patsubst(`GNUs not Unix', `\<', `OBS: ') +patsubst(`GNUs not Unix', `\<\w', `\0=') +patsubst(`GNUs not Unix', `\w*', `(\0)') +patsubst(`GNUs not Unix', `\w+', `(\0)') +patsubst(`GNUs not Unix', `\w+') +patsubst(`GNUs not Unix', `[ ]+', ` ') diff --git a/examples/patsubst.test b/examples/patsubst.test new file mode 100755 index 00000000..c31c4c5d --- /dev/null +++ b/examples/patsubst.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# patsubst.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/patsubst.m4 >in + +cat <<\EOF >ok +# traceon(`patsubst') +OBS: GNUs not Unix +OBS: GNUs OBS: not OBS: Unix +G=NUs n=ot U=nix +(GNUs)() (not)() (Unix) +(GNUs) (not) (Unix) + +GNUs not Unix +EOF + +cat <<\EOF >okerr +in:4: m4: WARNING: \0 will disappear, use \& instead in replacements +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/pushpop.m4 b/examples/pushpop.m4 new file mode 100644 index 00000000..d0f2ebb8 --- /dev/null +++ b/examples/pushpop.m4 @@ -0,0 +1,25 @@ +divert(-1) +pushdef(`hej', `def 1.') +dumpdef(`hej') +pushdef(`hej', `def 2.') +dumpdef(`hej') +pushdef(`hej', `def 3.') +dumpdef(`hej') +pushdef(`hej', `def 4.') +dumpdef(`hej') + +popdef(`hej') +dumpdef(`hej') +popdef(`hej') +dumpdef(`hej') +popdef(`hej') +dumpdef(`hej') +popdef(`hej') +dumpdef(`hej') +popdef(`hej') +dumpdef(`hej') +popdef(`hej') + +dumpdef(`mac2') +popdef(`mac2') +dumpdef(`mac2') diff --git a/examples/pushpop.test b/examples/pushpop.test new file mode 100755 index 00000000..038aca15 --- /dev/null +++ b/examples/pushpop.test @@ -0,0 +1,28 @@ +#!/bin/sh + +# pushpop.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/pushpop.m4 >in + +cat <<\EOF >ok +EOF + +cat <<\EOF >okerr +hej: `def 1.' +hej: `def 2.' +hej: `def 3.' +hej: `def 4.' +hej: `def 3.' +hej: `def 2.' +hej: `def 1.' +in:18: m4: Undefined name hej +in:20: m4: Undefined name hej +in:23: m4: Undefined name mac2 +in:25: m4: Undefined name mac2 +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/regexp.m4 b/examples/regexp.m4 new file mode 100644 index 00000000..a4ca573e --- /dev/null +++ b/examples/regexp.m4 @@ -0,0 +1,12 @@ +traceon(`regexp')dnl +regexp(`hej med dig', `.*', `>>\0<<') +regexp(`hej med dig', `\w*', `>>\0<<') +regexp(`hej med dig', `.+', `>>\0<<') +regexp(`hej med dig', `m\w+', `>>\0<<') +regexp(`hej med dig', `m\(.*\)', `>>\0<< >>\1<<') + +regexp(`hej med dig', `.*') +regexp(`hej med dig', `\w*') +regexp(`hej med dig', `.+') +regexp(`hej med dig', `m\w+') +regexp(`hej med dig', `m\(.*\)') diff --git a/examples/regexp.test b/examples/regexp.test new file mode 100755 index 00000000..4cf21990 --- /dev/null +++ b/examples/regexp.test @@ -0,0 +1,39 @@ +#!/bin/sh + +# regexp.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/regexp.m4 >in + +cat <<\EOF >ok +>>hej med dig<< +>>hej<< +>>hej med dig<< +>>med<< +>>med dig<< >>ed dig<< + +0 +0 +0 +4 +4 +EOF + +cat <<\EOF >okerr +in:2: m4: WARNING: \0 will disappear, use \& instead in replacements +m4trace: -1- regexp(`hej med dig', `.*', `>>\0<<') -> `>>hej med dig<<' +m4trace: -1- regexp(`hej med dig', `\w*', `>>\0<<') -> `>>hej<<' +m4trace: -1- regexp(`hej med dig', `.+', `>>\0<<') -> `>>hej med dig<<' +m4trace: -1- regexp(`hej med dig', `m\w+', `>>\0<<') -> `>>med<<' +m4trace: -1- regexp(`hej med dig', `m\(.*\)', `>>\0<< >>\1<<') -> `>>med dig<< >>ed dig<<' +m4trace: -1- regexp(`hej med dig', `.*') -> `0' +m4trace: -1- regexp(`hej med dig', `\w*') -> `0' +m4trace: -1- regexp(`hej med dig', `.+') -> `0' +m4trace: -1- regexp(`hej med dig', `m\w+') -> `4' +m4trace: -1- regexp(`hej med dig', `m\(.*\)') -> `4' +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/reverse.m4 b/examples/reverse.m4 new file mode 100644 index 00000000..1e620088 --- /dev/null +++ b/examples/reverse.m4 @@ -0,0 +1,4 @@ +define(`reverse', `ifelse(eval($# > 1), 1, `reverse(shift($@)), `$1'', ``$1'')') +``'' => reverse +``hej'' => reverse(hej) +``hej, med, dig'' => reverse(hej, med, dig) diff --git a/examples/reverse.test b/examples/reverse.test new file mode 100755 index 00000000..63b4cefa --- /dev/null +++ b/examples/reverse.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# reverse.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(reverse.m4)dnl +EOF + +cat <<\EOF >ok + +`' => +`hej' => hej +`hej, med, dig' => dig, med, hej +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok diff --git a/examples/stackovf.sh b/examples/stackovf.sh new file mode 100644 index 00000000..e389a210 --- /dev/null +++ b/examples/stackovf.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +# Script to verify that stack overflow is diagnosed properly when +# there is infinite macro call nesting. +# (causes coredump in m4-1.0.3) + +# On some systems the ulimit command is available in ksh or bash but not sh +(exec 2>/dev/null; ulimit -HSs 300) || { + for altshell in bash bsh ksh ; do + if (exec >/dev/null 2>&1; $altshell -c 'ulimit -HSs 300') && + test -z "$1" + then + echo "Using $altshell because it supports ulimit" + exec $altshell $0 running-with-$altshell + exit 9 + fi + done +} + +PATH=.:..:$PATH; export PATH; +M4=m4 +type $M4 + +tmpfile=/tmp/t.$$ +trap 'rm -f $tmpfile; exit 1' 1 2 3 15 + +rm -f core +perl -e ' +# Generate nested define sequence +$max=1000000; +for ($i=0; $i<$max; $i++) { + print "define(X$i,\n"; +} +for ($i=$max-1; $i>=0; $i--) { + print "body with substance no. $i)dnl\n" +} +' | \ +( +# Limit the stack size if the shell we are running permits it +if (exec 2>/dev/null; ulimit -HSs 50) +then + (exec >/dev/null 2>&1; ulimit -v) && ulimitdashv=ok + ulimit -HSs 50 + #ulimit -HSd 8000 + #test -n "$ulimitdashv" && ulimit -HSv 8000 + echo "Stack limit is `ulimit -s`K"; + echo "Heap limit is `ulimit -d`K"; + test -n "$ulimitdashv" && + echo "VMem limit is `ulimit -v`K"; +else + echo "Can't reset stack limit - this may take a while..." +fi +$M4 -L999999999 > $tmpfile 2>&1 +) +result=$? + +exitcode=1 +if test $result -eq 0 ; then + echo "TEST DID NOT WORK - m4 did not abort. Output:" +else + # See if stack overflow was diagnosed + case "`cat $tmpfile`" in + *overflow*) + echo "Test succeeded."; + exitcode=0 + ;; + *ut*of*emory*) + echo "*** Test is INCONCLUSIVE (ran out of heap before stack overflow)"; + ;; + *) echo "*** Test FAILED. $M4 aborted unexpectedly. Output:"; + ;; + esac +fi + +if test -f core ; then + ls -l core + exitcode=1 +fi + +#(test $exitcode -ne 0) && + { echo "Output from $M4:"; cat $tmpfile; } + +exit $exitcode diff --git a/examples/sync-lines.m4 b/examples/sync-lines.m4 new file mode 100644 index 00000000..405ab618 --- /dev/null +++ b/examples/sync-lines.m4 @@ -0,0 +1,11 @@ +# Several input lines, expanding to one +define(`foo', ``foo' line one. +`foo' line two. +`foo' line three.') xyz +foo +# Several input lines, expanding to none +define(`foo', ``foo' line one. +`foo' line two. +`foo' line three.')dnl +# one input line, expanding to several output lines +foo foo diff --git a/examples/sysv-args.m4 b/examples/sysv-args.m4 new file mode 100644 index 00000000..7c82beb0 --- /dev/null +++ b/examples/sysv-args.m4 @@ -0,0 +1,14 @@ +divert(-1) +define(`nargs', `$#') +define(`concat', `ifelse(1, $#, `$1', `$1` 'concat(shift($@))')') +traceon(`concat', `nargs') +divert + +nargs +nargs() +nargs(1,2,3,4,5,6) + +concat() +concat(`hej', `med', `dig') +concat(`hej', `med', `dig', `en gang igen') +concat(an, awful, lot, of, argument, at, least, more, that, ten, silly, arguments) diff --git a/examples/sysv-args.test b/examples/sysv-args.test new file mode 100755 index 00000000..ceb68c9a --- /dev/null +++ b/examples/sysv-args.test @@ -0,0 +1,53 @@ +#!/bin/sh + +# sysv-args.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(sysv-args.m4)dnl +EOF + +cat <<\EOF >ok + + +0 +1 +6 + + +hej med dig +hej med dig en gang igen +an awful lot of argument at least more that ten silly arguments +EOF + +cat <<\EOF >okerr +m4trace: -1- nargs +m4trace: -1- nargs +m4trace: -1- nargs +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +m4trace: -1- concat +EOF + +M4PATH=$srcdir $M4 in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/trace.m4 b/examples/trace.m4 new file mode 100644 index 00000000..a79dbcdd --- /dev/null +++ b/examples/trace.m4 @@ -0,0 +1,30 @@ +divert(-1) + +# move(from, to) +define(`move', `Move one disk from `$1' to `$2'. +') + +# _hanoi (cnt, from, to, aux) +define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', +`_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')') + +# hanoi (cnt) +define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)') +divert`'dnl + +# Debugmode t +debugmode(`t') +hanoi(2) + +# Debugmode taeq +debugmode(`taeq') +hanoi(2) + +# Debugmode OFF +debugmode +hanoi(2) + +# Debugmode ae +debugmode(`ae') +traceon(`move', `_hanoi') +hanoi(2) diff --git a/examples/trace.test b/examples/trace.test new file mode 100755 index 00000000..47008f60 --- /dev/null +++ b/examples/trace.test @@ -0,0 +1,96 @@ +#!/bin/sh + +# trace.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/trace.m4 >in + +cat <<\EOF >ok + +# Debugmode t + +Move one disk from source to auxilliary. +Move one disk from source to destination. +Move one disk from auxilliary to destination. + + +# Debugmode taeq + +Move one disk from source to auxilliary. +Move one disk from source to destination. +Move one disk from auxilliary to destination. + + +# Debugmode OFF + +Move one disk from source to auxilliary. +Move one disk from source to destination. +Move one disk from auxilliary to destination. + + +# Debugmode ae + + +Move one disk from source to auxilliary. +Move one disk from source to destination. +Move one disk from auxilliary to destination. + +EOF + +cat <<\EOF >okerr +m4trace: -1- hanoi +m4trace: -1- _hanoi +m4trace: -2- eval +m4trace: -1- ifelse +m4trace: -2- decr +m4trace: -1- _hanoi +m4trace: -2- eval +m4trace: -1- ifelse +m4trace: -1- move +m4trace: -1- move +m4trace: -2- decr +m4trace: -1- _hanoi +m4trace: -2- eval +m4trace: -1- ifelse +m4trace: -1- move + +m4trace: -1- hanoi(`2') -> `_hanoi(`2', source, destination, auxilliary)' +m4trace: -1- _hanoi(`2', `source', `destination', `auxilliary') -> `ifelse(eval(`2'<=1), 1, `move(source, destination)', +`_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)')' +m4trace: -2- eval(`2<=1') -> `0' +m4trace: -1- ifelse(`0', `1', `move(source, destination)', `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)') -> `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)' +m4trace: -2- decr(`2') -> `1' +m4trace: -1- _hanoi(`1', `source', `auxilliary', `destination') -> `ifelse(eval(`1'<=1), 1, `move(source, auxilliary)', +`_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)')' +m4trace: -2- eval(`1<=1') -> `1' +m4trace: -1- ifelse(`1', `1', `move(source, auxilliary)', `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)') -> `move(source, auxilliary)' +m4trace: -1- move(`source', `auxilliary') -> `Move one disk from `source' to `auxilliary'. +' +m4trace: -1- move(`source', `destination') -> `Move one disk from `source' to `destination'. +' +m4trace: -2- decr(`2') -> `1' +m4trace: -1- _hanoi(`1', `auxilliary', `destination', `source') -> `ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)', +`_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)')' +m4trace: -2- eval(`1<=1') -> `1' +m4trace: -1- ifelse(`1', `1', `move(auxilliary, destination)', `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)') -> `move(auxilliary, destination)' +m4trace: -1- move(`auxilliary', `destination') -> `Move one disk from `auxilliary' to `destination'. +' +m4trace: -1- debugmode +m4trace: -1- _hanoi(2, source, destination, auxilliary) -> ifelse(eval(`2'<=1), 1, `move(source, destination)', +`_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)') +m4trace: -1- _hanoi(1, source, auxilliary, destination) -> ifelse(eval(`1'<=1), 1, `move(source, auxilliary)', +`_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)') +m4trace: -1- move(source, auxilliary) -> Move one disk from `source' to `auxilliary'. + +m4trace: -1- move(source, destination) -> Move one disk from `source' to `destination'. + +m4trace: -1- _hanoi(1, auxilliary, destination, source) -> ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)', +`_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)') +m4trace: -1- move(auxilliary, destination) -> Move one disk from `auxilliary' to `destination'. + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/examples/translit.m4 b/examples/translit.m4 new file mode 100644 index 00000000..078d1726 --- /dev/null +++ b/examples/translit.m4 @@ -0,0 +1,8 @@ +# traceon(`translit')dnl +translit(`GNUs not Unix', `a-z') +translit(`GNUs not Unix', `a-z', `A-Z') +translit(`GNUs not Unix', `A-Z', `a-z') +translit(`GNUs not Unix', `A-Z') +translit(`a-z', `a-') +translit(`A-Z', `A-Z-', `-A-Z') +translit(`GNUs not Unix', `Z-A', `a-z') diff --git a/examples/translit.test b/examples/translit.test new file mode 100755 index 00000000..92acfb62 --- /dev/null +++ b/examples/translit.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# translit.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/translit.m4 >in + +cat <<\EOF >ok +# traceon(`translit')dnl +GNU U +GNUS NOT UNIX +gnus not unix +s not nix +z +-ZY +tmfs not fnix +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/undivert.incl b/examples/undivert.incl new file mode 100644 index 00000000..408e0e20 --- /dev/null +++ b/examples/undivert.incl @@ -0,0 +1 @@ +This is to be undiverted soon. diff --git a/examples/undivert.m4 b/examples/undivert.m4 new file mode 100644 index 00000000..61dfb391 --- /dev/null +++ b/examples/undivert.m4 @@ -0,0 +1,5 @@ +define(`undiverted', `UNDIVERTED') +# undiverted file. +undivert(`undivert.incl') +# included file. +include(`undivert.incl') diff --git a/examples/undivert.test b/examples/undivert.test new file mode 100755 index 00000000..6814a732 --- /dev/null +++ b/examples/undivert.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# undivert.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/undivert.m4 >in + +cat <<\EOF >ok + +# undiverted file. +This is to be undiverted soon. + +# included file. +This is to be UNDIVERTED soon. + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/examples/wrap.m4 b/examples/wrap.m4 new file mode 100644 index 00000000..bbe7ae0b --- /dev/null +++ b/examples/wrap.m4 @@ -0,0 +1,10 @@ +divert(-1) +m4wrap(`Wrapper no. 1 +') + +m4wrap(`Wrapper no. 2 +m4wrap(`Wrapper no. 3 +m4wrap(`Wrapper no. 4 +')')') +divert +No. 33: The End. diff --git a/examples/wrap.test b/examples/wrap.test new file mode 100755 index 00000000..a6bba3c2 --- /dev/null +++ b/examples/wrap.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# wrap.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat <<\EOF >in +include(wrap.m4)dnl +EOF + +cat <<\EOF >ok + +No. 33: The End. +Wrapper no. 2 +Wrapper no. 1 +Wrapper no. 3 +Wrapper no. 4 +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok diff --git a/gettext.m4 b/gettext.m4 new file mode 100644 index 00000000..969d0922 --- /dev/null +++ b/gettext.m4 @@ -0,0 +1,384 @@ +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# Modified for GNU m4 by René Seindal (rene@seindal.dk) + +# serial 5 + +AC_DEFUN(AM_WITH_NLS, + [AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) + + USE_INCLUDED_LIBINTL=no + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + AC_DEFINE(ENABLE_NLS) + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc, + [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")], + gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)]) + + if test "$gt_cv_func_gettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, gettext, + [LIBS="$LIBS -lintl" + gt_cv_func_gettext_libintl=yes], + [gt_cv_func_gettext_libintl=no])]) + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + ]) + + if test "$CATOBJEXT" = "NONE"; then + AC_MSG_CHECKING([whether catgets can be used]) + AC_ARG_WITH(catgets, + [ --with-catgets use catgets functions if available], + nls_cv_use_catgets=$withval, nls_cv_use_catgets=no) + AC_MSG_RESULT($nls_cv_use_catgets) + + if test "$nls_cv_use_catgets" = "yes"; then + dnl No gettext in C library. Try catgets next. + AC_CHECK_LIB(i, main) + AC_CHECK_FUNC(catgets, + [AC_DEFINE(HAVE_CATGETS) + INTLOBJS="\$(CATOBJS)" + AC_PATH_PROG(GENCAT, gencat, no)dnl + if test "$GENCAT" != "no"; then + AC_PATH_PROG(GMSGFMT, gmsgfmt, no) + if test "$GMSGFMT" = "no"; then + AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no) + fi + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.cat + INSTOBJEXT=.cat + DATADIRNAME=lib + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi]) + fi + fi + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + INTLOBJS="\$(GETTOBJS)" + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_SUBST(MSGFMT) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(AM_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next]) + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + AC_CHECK_FUNCS(stpcpy) + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + AC_DEFINE(HAVE_STPCPY) + fi + + AM_LC_MESSAGES + AM_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl The reference to <locale.h> in the installed <libintl.h> file + dnl must be resolved because we cannot expect the users of this + dnl to define HAVE_LOCALE_H. + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include <locale.h>" + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header <locale.h>. Take care yourself. */" + fi + AC_SUBST(INCLUDE_LOCALE_H) + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + test -d intl || mkdir intl + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed + fi + dnl po2tbl.sed is always needed. + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed + + dnl In the intl/Makefile.in we have a special dependency which makes + dnl only sense for gettext. We comment this out for non-gettext + dnl packages. + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + AC_SUBST(GT_NO) + AC_SUBST(GT_YES) + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl *** For now the libtool support in intl/Makefile is not for real. + l= + AC_SUBST(l) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper <drepper@cygnus.com>, 1996. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in <locale.h>. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES) + fi + fi]) + diff --git a/install-sh b/install-sh new file mode 100755 index 00000000..ab74c882 --- /dev/null +++ b/install-sh @@ -0,0 +1,238 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/lib/COPYING.LIB b/lib/COPYING.LIB new file mode 100644 index 00000000..bbe3fe19 --- /dev/null +++ b/lib/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..c7c06190 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,12 @@ +## Process this file with automake to produce Makefile.in +noinst_LIBRARIES = libm4.a + +libm4_a_SOURCES = getopt.h obstack.h regex.h regex.c getopt.c \ + getopt1.c error.c obstack.c xmalloc.c \ + xstrdup.c alloca.c strtol.c + +noinst_HEADERS = getopt.h error.h getdate.h + +libm4_a_LIBADD = +libm4_a_DEPENDENCIES = # $(libfu_a_LIBADD) + diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 00000000..82ea2ed7 --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,92 @@ +# Makefile for GNU m4 library. +# Copyright (C) 1992, 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +PRODUCT = @PRODUCT@ +VERSION = @VERSION@ + +SHELL = /bin/sh +srcdir = @srcdir@ +VPATH = @srcdir@ + +AR = ar +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +RANLIB = @RANLIB@ + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) + +.SUFFIXES: +.SUFFIXES: .c .o +.c.o: + $(COMPILE) $< + +INCLUDES = -I.. -I$(srcdir) + +HEADERS = getopt.h obstack.h regex.h +SOURCES = regex.c getopt.c getopt1.c error.c obstack.c xmalloc.c \ +xstrdup.c alloca.c strtol.c +OBJECTS = regex.o getopt.o getopt1.o error.o obstack.o xmalloc.o \ +xstrdup.o @ALLOCA@ @LIBOBJS@ + +DISTFILES = COPYING.LIB Makefile.in $(HEADERS) $(SOURCES) \ +TAGS + +all: libm4.a + +libm4.a: $(OBJECTS) + rm -f libm4.a + $(AR) cru libm4.a $(OBJECTS) + $(RANLIB) libm4.a + +$(OBJECTS): ../config.h + +install: all + +uninstall: + +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) + cd $(srcdir) && etags $(HEADERS) $(SOURCES) + +mostlyclean: + rm -f *.o + +clean: mostlyclean + rm -f libm4.a + +distclean: clean + rm -f Makefile + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + @echo "Copying distribution files" + @for file in $(DISTFILES); do \ + ln $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/lib 2> /dev/null \ + || cp -p $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/lib; \ + done + +Makefile: Makefile.in ../config.status + cd .. && CONFIG_FILES=lib/$@ CONFIG_HEADERS= ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/alloca.c b/lib/alloca.c new file mode 100644 index 00000000..7020f32c --- /dev/null +++ b/lib/alloca.c @@ -0,0 +1,492 @@ +/* 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 <jot@cray.com> 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. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef emacs +#include "blockinput.h" +#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 +#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 + +#if __STDC__ +typedef void *pointer; +#else +typedef char *pointer; +#endif + +#define NULL 0 + +/* Different portions of Emacs need to call different versions of + malloc. The Emacs executable needs alloca to call xmalloc, because + ordinary malloc isn't protected from input signals. On the other + hand, the utilities in lib-src need alloca to call malloc; some of + them are very simple, and don't have an xmalloc routine. + + Non-Emacs programs expect this to call use xmalloc. + + Callers below should use malloc. */ + +#ifndef emacs +#define malloc xmalloc +#endif +extern pointer malloc (); + +/* 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 () +{ + 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. */ + +pointer +alloca (size) + unsigned 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 ((pointer) 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. */ + + { + register pointer new = malloc (sizeof (header) + size); + /* Address of header. */ + + ((header *) new)->h.next = last_alloca_header; + ((header *) new)->h.deep = depth; + + last_alloca_header = (header *) new; + + /* User storage begins just after header. */ + + return (pointer) ((char *) new + sizeof (header)); + } +} + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) + +#ifdef DEBUG_I00AFUNC +#include <stdio.h> +#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/lib/error.c b/lib/error.c new file mode 100644 index 00000000..19c2ba88 --- /dev/null +++ b/lib/error.c @@ -0,0 +1,119 @@ +/* error.c -- error handler for noninteractive utilities + Copyright (C) 1990, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> + +#if HAVE_VPRINTF || HAVE_DOPRNT +# if __STDC__ +# include <stdarg.h> +# define VA_START(args, lastarg) va_start(args, lastarg) +# else +# include <varargs.h> +# define VA_START(args, lastarg) va_start(args) +# endif +#else +# define va_alist a1, a2, a3, a4, a5, a6, a7, a8 +# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; +#endif + +#if STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +void exit (); +#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) () = NULL; + +/* The calling program should define program_name and set it to the + name of the executing program. */ +extern char *program_name; + +#if HAVE_STRERROR +char *strerror (); +#else +static char * +private_strerror (errnum) + int errnum; +{ + extern char *sys_errlist[]; + extern int sys_nerr; + + if (errnum > 0 && errnum <= sys_nerr) + return sys_errlist[errnum]; + return "Unknown system error"; +} +#define strerror private_strerror +#endif + +/* 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. */ +/* VARARGS */ + +void +#if defined(VA_START) && __STDC__ +error (int status, int errnum, const char *message, ...) +#else +error (status, errnum, message, va_alist) + int status; + int errnum; + char *message; + va_dcl +#endif +{ +#ifdef VA_START + va_list args; +#endif + + if (error_print_progname) + (*error_print_progname) (); + else + { + fflush (stdout); + fprintf (stderr, "%s: ", program_name); + } + +#ifdef VA_START + VA_START (args, message); +# if HAVE_VPRINTF + vfprintf (stderr, message, args); +# else + _doprnt (message, args, stderr); +# endif + va_end (args); +#else + fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); +#endif + + if (errnum) + fprintf (stderr, ": %s", strerror (errnum)); + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (status); +} diff --git a/lib/error.h b/lib/error.h new file mode 100644 index 00000000..7a803d0c --- /dev/null +++ b/lib/error.h @@ -0,0 +1,65 @@ +/* error.h -- declaration for error-reporting function + Copyright (C) 1995, 1996 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. */ + +#ifndef ERROR_H_ +# define ERROR_H_ + +# 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 + +# if defined (__STDC__) && __STDC__ + +/* 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); + +# else +void error (); +void error_at_line (); +extern void (*error_print_progname) (); +# endif + +/* 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; + +#endif /* not ERROR_H_ */ diff --git a/lib/getdate.h b/lib/getdate.h new file mode 100644 index 00000000..db2dba4b --- /dev/null +++ b/lib/getdate.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1995 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. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +# ifndef PARAMS +# if defined (__GNUC__) || __STDC__ +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +# endif + +#if defined (vms) +# include <types.h> +# include <time.h> +#else +# include <sys/types.h> +# ifdef TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +# else +# ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +# endif +#endif /* defined (vms) */ + +time_t get_date PARAMS ((const char *p, const time_t *now)); diff --git a/lib/getopt.c b/lib/getopt.c new file mode 100644 index 00000000..43c0a6a9 --- /dev/null +++ b/lib/getopt.c @@ -0,0 +1,748 @@ +/* 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 roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 + 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. 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. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#endif /* GNU C library. */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' 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. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the 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.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 = NULL; + +/* 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 EOF, 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. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* 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. */ + +static char *nextchar; + +/* 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 = '?'; + +/* 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. + + 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 EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* 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. */ + +static int first_nonopt; +static int last_nonopt; + +/* 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 (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = 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. */ + + 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; + } + /* 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; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (optstring) + const char *optstring; +{ + /* 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. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + 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 `EOF'. + 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. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + 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. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0) + optstring = _getopt_initialize (optstring); + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + optind++; + last_nonopt = 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 (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + 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 (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* 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 ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[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[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound; + int option_index; + + for (nameend = 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, nextchar, nameend - nextchar)) + { + if (nameend - 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 (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + 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) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (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[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); + else + fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + 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 == EOF) + 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/lib/getopt.h b/lib/getopt.h new file mode 100644 index 00000000..4ac33b71 --- /dev/null +++ b/lib/getopt.h @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 90, 91, 92, 93, 94 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#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 EOF, 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; + +/* 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 +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* 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 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/lib/getopt1.c b/lib/getopt1.c new file mode 100644 index 00000000..4580211c --- /dev/null +++ b/lib/getopt1.c @@ -0,0 +1,180 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994 + 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "getopt.h" + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. 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. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* 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 (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + 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 == EOF) + 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/lib/m4error.c b/lib/m4error.c new file mode 100644 index 00000000..5a0d7bdd --- /dev/null +++ b/lib/m4error.c @@ -0,0 +1,259 @@ +/* Error handler for noninteractive utilities + Copyright (C) 1990,91,92,93,94,95,96,97,98 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC +# if __STDC__ +# include <stdarg.h> +# define VA_START(args, lastarg) va_start(args, lastarg) +# else +# include <varargs.h> +# define VA_START(args, lastarg) va_start(args) +# endif +#else +# define va_alist a1, a2, a3, a4, a5, a6, a7, a8 +# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; +#endif + +#if STDC_HEADERS || _LIBC +# include <stdlib.h> +# include <string.h> +#else +void exit (); +#endif + +#ifndef _ +# define _(String) String +#endif + +/* Get prototypes for the functions defined here. */ +#include <m4error.h> + +#ifdef DLL_EXPORT +# define M4_GLOBAL_DATA __declspec(dllexport) +#else +# define M4_GLOBAL_DATA +#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. */ +M4_GLOBAL_DATA void (*error_print_progname) ( +#if __STDC__ - 0 + void +#endif + ); + +/* This variable is incremented each time `error' is called. */ +M4_GLOBAL_DATA 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 <errno.h> + +/* In GNU libc we want do not want to use the common name `error' directly. + Instead make it a weak alias. */ +# define error __error +# define error_at_line __error_at_line + +# ifdef USE_IN_LIBIO +# include <libio/iolibio.h> +# define fflush(s) _IO_fflush (s) +# endif + +#else /* not _LIBC */ + +/* The calling program should define program_name and set it to the + name of the executing program. */ +M4_GLOBAL_DATA char *program_name; + +# ifdef HAVE_STRERROR_R +# define __strerror_r strerror_r +# else +# if HAVE_STRERROR +# ifndef strerror /* On some systems, strerror is a macro */ +char *strerror (); +# endif +# else +static char * +private_strerror (errnum) + int errnum; +{ + extern char *sys_errlist[]; + extern int sys_nerr; + + if (errnum > 0 && errnum <= sys_nerr) + return _(sys_errlist[errnum]); + return _("Unknown system error"); +} +# define strerror private_strerror +# endif /* HAVE_STRERROR */ +# endif /* HAVE_STRERROR_R */ +#endif /* not _LIBC */ + +/* 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. */ +/* VARARGS */ + +void +#if defined VA_START && __STDC__ +error (int status, int errnum, const char *message, ...) +#else +error (status, errnum, message, va_alist) + int status; + int errnum; + char *message; + va_dcl +#endif +{ +#ifdef VA_START + va_list args; +#endif + + if (error_print_progname) + (*error_print_progname) (); + else + { + fflush (stdout); + fprintf (stderr, "%s: ", program_name); + } + +#ifdef VA_START + VA_START (args, message); +# if HAVE_VPRINTF || _LIBC + vfprintf (stderr, message, args); +# else + _doprnt (message, args, stderr); +# endif + va_end (args); +#else + fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); +#endif + + ++error_message_count; + if (errnum) + { +#if defined HAVE_STRERROR_R || defined _LIBC + char errbuf[1024]; + fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf)); +#else + fprintf (stderr, ": %s", strerror (errnum)); +#endif + } + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (status); +} + +/* 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 +#if defined VA_START && __STDC__ +error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, ...) +#else +error_at_line (status, errnum, file_name, line_number, message, va_alist) + int status; + int errnum; + const char *file_name; + unsigned int line_number; + char *message; + va_dcl +#endif +{ +#ifdef VA_START + va_list args; +#endif + + 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))) + /* Simply return and print nothing. */ + return; + + old_file_name = file_name; + old_line_number = line_number; + } + + if (error_print_progname) + (*error_print_progname) (); + else + { + fflush (stdout); + fprintf (stderr, "%s:", program_name); + } + + if (file_name != NULL) + fprintf (stderr, "%s:%d: ", file_name, line_number); + +#ifdef VA_START + VA_START (args, message); +# if HAVE_VPRINTF || _LIBC + vfprintf (stderr, message, args); +# else + _doprnt (message, args, stderr); +# endif + va_end (args); +#else + fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); +#endif + + ++error_message_count; + if (errnum) + { +#if defined HAVE_STRERROR_R || defined _LIBC + char errbuf[1024]; + fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf)); +#else + fprintf (stderr, ": %s", strerror (errnum)); +#endif + } + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (status); +} + +#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/lib/m4error.h b/lib/m4error.h new file mode 100644 index 00000000..066ffec4 --- /dev/null +++ b/lib/m4error.h @@ -0,0 +1,98 @@ +/* Declaration for error-reporting function + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef M4ERROR_H +#define M4ERROR_H 1 + +/* DLL building support on win32 hosts; mostly to workaround their + ridiculous implementation of data symbol exporting. */ +#ifndef M4_SCOPE +# ifdef _WIN32 + /* Incase we are linking a dll with this library, the + LIBM4_DLL_IMPORT takes precedence over a generic DLL_EXPORT + when defining the SCOPE variable for M4. */ +# ifdef LIBM4_DLL_IMPORT /* define if linking with this dll */ +# define M4_SCOPE extern __declspec(dllimport) +# else +# ifdef DLL_EXPORT /* defined by libtool (if required) */ +# define M4_SCOPE __declspec(dllexport) +# endif /* DLL_EXPORT */ +# endif /* LIBM4_DLL_IMPORT */ +# endif /* M4_SCOPE */ +# ifndef M4_SCOPE /* static linking or !_WIN32 */ +# define M4_SCOPE extern +# endif +#endif + + +#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 + +#if defined (__STDC__) && __STDC__ + +/* 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. */ +M4_SCOPE void (*error_print_progname) (void); + +#else +void error (); +void error_at_line (); +M4_SCOPE void (*error_print_progname) (); +#endif + +/* This variable is incremented each time `error' is called. */ +M4_SCOPE 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. */ +M4_SCOPE int error_one_per_line; + +#ifdef __cplusplus +} +#endif + +#endif /* m4error.h */ diff --git a/lib/m4module.c b/lib/m4module.c new file mode 100644 index 00000000..b22d8b85 --- /dev/null +++ b/lib/m4module.c @@ -0,0 +1,214 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94, 98 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#define COMPILING_M4 +#include "m4module.h" +#include "m4private.h" + +#ifdef DLL_EXPORT +# define M4_GLOBAL_DATA __declspec(dllexport) +#else +# define M4_GLOBAL_DATA +#endif + +/* The name this program was run with. */ +M4_GLOBAL_DATA const char *program_name; + +/* Operate interactively (-e). */ +M4_GLOBAL_DATA int interactive = 0; + +/* Enable sync output for /lib/cpp (-s). */ +M4_GLOBAL_DATA int sync_output = 0; + +/* Debug (-d[flags]). */ +M4_GLOBAL_DATA int debug_level = 0; + +/* Hash table size (should be a prime) (-Hsize). */ +M4_GLOBAL_DATA int hash_table_size = HASHMAX; + +/* Disable GNU extensions (-G). */ +M4_GLOBAL_DATA int no_gnu_extensions = 0; + +/* Prefix all builtin functions by `m4_'. */ +M4_GLOBAL_DATA int prefix_all_builtins = 0; + +/* Max length of arguments in trace output (-lsize). */ +M4_GLOBAL_DATA int max_debug_argument_length = 0; + +/* Suppress warnings about missing arguments. */ +M4_GLOBAL_DATA int suppress_warnings = 0; + +/* If not zero, then value of exit status for warning diagnostics. */ +M4_GLOBAL_DATA int warning_status = 0; + +/* Artificial limit for expansion_level in macro.c. */ +M4_GLOBAL_DATA int nesting_limit = 250; + +/* User provided regexp for describing m4 words. */ +M4_GLOBAL_DATA const char *user_word_regexp = NULL; + +/* If nonzero, comments are discarded in the token parser. */ +M4_GLOBAL_DATA int discard_comments = 0; + +/* input syntax table. */ +M4_GLOBAL_DATA unsigned short syntax_table[256]; + +/* Quote chars. */ +M4_GLOBAL_DATA STRING rquote; +M4_GLOBAL_DATA STRING lquote; + +/* Comment chars. */ +M4_GLOBAL_DATA STRING bcomm; +M4_GLOBAL_DATA STRING ecomm; + + +/*------------------------------------------------------------------------. +| Addressable function versions of the macros defined in m4private.h. | +| Since they are functions the caller does not need access to the | +| internal data structure, so they are safe to export for use in | +| external modules. | +`------------------------------------------------------------------------*/ +token_data_type +m4_token_data_type (token_data *name) +{ + return TOKEN_DATA_TYPE(name); +} + +char * +m4_token_data_text (token_data *name) +{ + return TOKEN_DATA_TEXT(name); +} + +char * +m4_token_data_orig_text (token_data *name) +{ +#ifdef ENABLE_CHANGEWORD + return TOKEN_DATA_ORIG_TEXT(name); +#else + return NULL; +#endif +} + +builtin_func * +m4_token_data_func (token_data *name) +{ + return TOKEN_DATA_FUNC(name); +} + +boolean +m4_token_data_func_traced (token_data *name) +{ + return TOKEN_DATA_FUNC_TRACED(name); +} + + +/*------------------------------------------------------------------------. +| 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. | +`------------------------------------------------------------------------*/ + +boolean +m4_bad_argc (token_data *name, int argc, int min, int max) +{ + boolean isbad = FALSE; + + if (min > 0 && argc < min) + { + if (!suppress_warnings) + M4ERROR ((warning_status, 0, + _("Warning: Too few arguments to built-in `%s'"), + TOKEN_DATA_TEXT (name))); + isbad = TRUE; + } + else if (max > 0 && argc > max && !suppress_warnings) + M4ERROR ((warning_status, 0, + _("Warning: Excess arguments to built-in `%s' ignored"), + TOKEN_DATA_TEXT (name))); + + return isbad; +} + +const char * +m4_skip_space (const char *arg) +{ + while (IS_SPACE(*arg)) + arg++; + return arg; +} + +/*--------------------------------------------------------------------------. +| The function m4_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. | +`--------------------------------------------------------------------------*/ +boolean +m4_numeric_arg (token_data *macro, const char *arg, int *valuep) +{ + char *endp; + + if (*arg == 0 || (*valuep = strtol (m4_skip_space(arg), &endp, 10), + *m4_skip_space(endp) != 0)) + { + M4ERROR ((warning_status, 0, + _("Non-numeric argument to built-in `%s'"), + TOKEN_DATA_TEXT (macro))); + return FALSE; + } + return TRUE; +} + +/*----------------------------------------------------------------------. +| Format an int VAL, and stuff it into an obstack OBS. Used for macros | +| expanding to numbers. | +`----------------------------------------------------------------------*/ + +void +m4_shipout_int (struct obstack *obs, int val) +{ + char buf[128]; + + sprintf(buf, "%d", val); + obstack_grow (obs, buf, strlen (buf)); +} + +void +m4_shipout_string (struct obstack *obs, const char *s, int len, boolean quoted) +{ + if (s == NULL) + s = ""; + + if (len == 0) + len = strlen(s); + + if (quoted) + obstack_grow (obs, lquote.string, lquote.length); + obstack_grow (obs, s, len); + if (quoted) + obstack_grow (obs, rquote.string, rquote.length); +} + diff --git a/lib/m4module.h b/lib/m4module.h new file mode 100644 index 00000000..74da7200 --- /dev/null +++ b/lib/m4module.h @@ -0,0 +1,240 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef M4MODULE_H +#define M4MODULE_H + +#include <sys/types.h> +#include <m4error.h> +#include <m4obstack.h> + +#ifdef ENABLE_NLS +#include <libintl.h> +#define _(Text) gettext ((Text)) +#else +#define _(Text) (Text) +#endif + +#ifndef M4_PARAMS +# ifdef __STDC__ +# define M4_PARAMS(Args) Args +# else +# define M4_PARAMS(Args) () +# endif +#endif + +/* DLL building support on win32 hosts; mostly to workaround their + ridiculous implementation of data symbol exporting. */ +#ifndef M4_SCOPE +# ifdef _WIN32 + /* Incase we are linking a dll with this library, the + LIBM4_DLL_IMPORT takes precedence over a generic DLL_EXPORT + when defining the SCOPE variable for M4. */ +# ifdef LIBM4_DLL_IMPORT /* define if linking with this dll */ +# define M4_SCOPE extern __declspec(dllimport) +# else +# ifdef DLL_EXPORT /* defined by libtool (if required) */ +# define M4_SCOPE __declspec(dllexport) +# endif /* DLL_EXPORT */ +# endif /* LIBM4_DLL_IMPORT */ +# endif /* M4_SCOPE */ +# ifndef M4_SCOPE /* static linking or !_WIN32 */ +# define M4_SCOPE extern +# endif +#endif + +#if __STDC__ +# define voidstar void * +#else +# define voidstar char * +#endif + +/* If FALSE is defined, we presume TRUE is defined too. In this case, + merely typedef boolean as being int. Or else, define these all. */ +#ifndef FALSE +/* Do not use `enum boolean': this tag is used in SVR4 <sys/types.h>. */ +typedef enum { FALSE = 0, TRUE = 1 } boolean; +#else +typedef int boolean; +#endif + + +/* Syntax table definitions. */ +/* Please read the comment at the top of input.c for details */ +M4_SCOPE unsigned short syntax_table[256]; + +/* These are simple values, not bit masks. There is no overlap. */ +#define SYNTAX_OTHER (0x0000) + +#define SYNTAX_IGNORE (0x0001) +#define SYNTAX_SPACE (0x0002) +#define SYNTAX_OPEN (0x0003) +#define SYNTAX_CLOSE (0x0004) +#define SYNTAX_COMMA (0x0005) +#define SYNTAX_DOLLAR (0x0006) /* not used yet */ +#define SYNTAX_ACTIVE (0x0007) +#define SYNTAX_ESCAPE (0x0008) + +/* These are values to be assigned to syntax table entries, but they are + used as bit masks with IS_ALNUM.*/ +#define SYNTAX_ALPHA (0x0010) +#define SYNTAX_NUM (0x0020) +#define SYNTAX_ALNUM (SYNTAX_ALPHA|SYNTAX_NUM) + +/* These are bit masks to AND with other categories. + See input.c for details. */ +#define SYNTAX_LQUOTE (0x0100) +#define SYNTAX_RQUOTE (0x0200) +#define SYNTAX_BCOMM (0x0400) +#define SYNTAX_ECOMM (0x0800) + +/* These bits define the syntax code of a character */ +#define SYNTAX_VALUE (0x00FF|SYNTAX_LQUOTE|SYNTAX_BCOMM) +#define SYNTAX_MASKS (0xFF00) + +#define IS_OTHER(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_OTHER) +#define IS_IGNORE(ch) ((syntax_table[(int)(ch)]) == SYNTAX_IGNORE) +#define IS_SPACE(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_SPACE) + +#define IS_OPEN(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_OPEN) +#define IS_CLOSE(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_CLOSE) +#define IS_COMMA(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_COMMA) +#define IS_DOLLAR(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_DOLLAR) +#define IS_ACTIVE(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_ACTIVE) + +#define IS_ESCAPE(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_ESCAPE) +#define IS_ALPHA(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_ALPHA) +#define IS_NUM(ch) ((syntax_table[(int)(ch)]&SYNTAX_VALUE) == SYNTAX_NUM) +#define IS_ALNUM(ch) (((syntax_table[(int)(ch)]) & SYNTAX_ALNUM) != 0) + +#define IS_LQUOTE(ch) (syntax_table[(int)(ch)] & SYNTAX_LQUOTE) +#define IS_RQUOTE(ch) (syntax_table[(int)(ch)] & SYNTAX_RQUOTE) +#define IS_BCOMM(ch) (syntax_table[(int)(ch)] & SYNTAX_BCOMM) +#define IS_ECOMM(ch) (syntax_table[(int)(ch)] & SYNTAX_ECOMM) + + +/* Various declarations. */ + +struct string + { + unsigned char *string; /* characters of the string */ + size_t length; /* length of the string */ + }; +typedef struct string STRING; + +/* Memory allocation. */ +voidstar xmalloc M4_PARAMS((unsigned int)); +voidstar xrealloc M4_PARAMS((voidstar, unsigned int)); +void xfree M4_PARAMS((voidstar)); +char *xstrdup M4_PARAMS((const char *)); +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free xfree + +/* Other library routines. */ +void error M4_PARAMS((int , int, const char *, ...)); + + +typedef void builtin_func (); + +typedef struct { + const char *name; + boolean gnu_extension; + boolean groks_macro_args; + boolean blind_if_no_args; + builtin_func *func; +} builtin; + +/* Various different token types. */ +typedef enum { + TOKEN_EOF, /* end of file */ + TOKEN_NONE, /* discardable token */ + TOKEN_STRING, /* a quoted string */ + TOKEN_SPACE, /* whitespace */ + TOKEN_WORD, /* an identifier */ + TOKEN_SIMPLE, /* a single character */ + TOKEN_MACDEF /* a macros definition (see "defn") */ +} token_type; + +/* The data for a token, a macro argument, and a macro definition. */ +typedef enum { + TOKEN_VOID, + TOKEN_TEXT, + TOKEN_FUNC +} token_data_type; + +typedef void module_init_t M4_PARAMS((struct obstack *)); +typedef void module_finish_t M4_PARAMS((void)); + +#ifdef COMPILING_M4 +typedef struct token_data token_data; +#else +typedef voidstar token_data; +#endif + +token_data_type m4_token_data_type M4_PARAMS((token_data *)); +char *m4_token_data_text M4_PARAMS((token_data *)); +char *m4_token_data_orig_text M4_PARAMS((token_data *)); +builtin_func *m4_token_data_func M4_PARAMS((token_data *)); +boolean m4_token_data_func_traced M4_PARAMS((token_data *)); + +#define M4ARG(i) (argc > (i) ? m4_token_data_text (argv[i]) : "") + +#define M4BUILTIN(name) \ + static void name M4_PARAMS((struct obstack *, int, token_data **)) + +/* Error handling. */ +#define M4ERROR(Arglist) (error Arglist) + +#define HASHMAX 509 /* default, overridden by -Hsize */ + +/* The name this program was run with. */ +M4_SCOPE const char *program_name; + +/* Option flags (defined in m4module.c; set in m4.c). */ +M4_SCOPE int interactive; /* -e */ +M4_SCOPE int sync_output; /* -s */ +M4_SCOPE int debug_level; /* -d */ +M4_SCOPE int hash_table_size; /* -H */ +M4_SCOPE int no_gnu_extensions; /* -G */ +M4_SCOPE int prefix_all_builtins; /* -P */ +M4_SCOPE int max_debug_argument_length; /* -l */ +M4_SCOPE int suppress_warnings; /* -Q */ +M4_SCOPE int warning_status; /* -E */ +M4_SCOPE int nesting_limit; /* -L */ +M4_SCOPE int discard_comments; /* -c */ +M4_SCOPE const char *user_word_regexp; /* -W */ + +/* left and right quote, begin and end comment */ +M4_SCOPE STRING lquote; +M4_SCOPE STRING rquote; + +M4_SCOPE STRING bcomm; +M4_SCOPE STRING ecomm; + +#define DEF_LQUOTE "`" +#define DEF_RQUOTE "\'" +#define DEF_BCOMM "#" +#define DEF_ECOMM "\n" + +boolean m4_bad_argc M4_PARAMS((token_data *, int, int, int)); +const char *m4_skip_space M4_PARAMS((const char *)); +boolean m4_numeric_arg M4_PARAMS((token_data *, const char *, int *)); +void m4_shipout_int M4_PARAMS((struct obstack *, int)); +void m4_shipout_string M4_PARAMS((struct obstack*, const char*, int, boolean)); + +#endif /* M4MODULE_H */ diff --git a/lib/m4obstack.c b/lib/m4obstack.c new file mode 100644 index 00000000..022b949f --- /dev/null +++ b/lib/m4obstack.c @@ -0,0 +1,598 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988-1994,96,97,98,99 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "m4obstack.h" + +/* 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 <stdio.h> /* Random thing to get __GNU_LIBRARY__. */ +#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 +#include <gnu-versions.h> +#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + + +#ifndef ELIDE_CODE + + +#if defined (__STDC__) && __STDC__ +#define POINTER void * +#else +#define POINTER char * +#endif + +/* Determine default alignment. */ +struct fooalign {char x; double d;}; +#define DEFAULT_ALIGNMENT \ + ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0)) +/* 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. */ +union fooround {long x; double d;}; +#define 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'. */ +#if defined (__STDC__) && __STDC__ +static void print_and_abort (void); +void (*obstack_alloc_failed_handler) (void) = print_and_abort; +#else +static void print_and_abort (); +void (*obstack_alloc_failed_handler) () = print_and_abort; +#endif + +/* Exit value used when `print_and_abort' is used. */ +#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +int obstack_exit_failure = EXIT_FAILURE; + +/* The non-GNU-C macros copy the obstack into this global variable + to avoid multiple evaluation. */ + +struct obstack *_obstack; + +/* 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. */ + +#if defined (__STDC__) && __STDC__ +#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) +#else +#define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size))) + +#define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) ()) (h)->freefun) ((old_chunk)); \ + } while (0) +#endif + + +/* 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 (h, size, alignment, chunkfun, freefun) + struct obstack *h; + int size; + int alignment; +#if defined (__STDC__) && __STDC__ + POINTER (*chunkfun) (long); + void (*freefun) (void *); +#else + POINTER (*chunkfun) (); + void (*freefun) (); +#endif +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = (int) 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; + } + +#if defined (__STDC__) && __STDC__ + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; +#else + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; +#endif + 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 = chunk->contents; + 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 (h, size, alignment, chunkfun, freefun, arg) + struct obstack *h; + int size; + int alignment; +#if defined (__STDC__) && __STDC__ + POINTER (*chunkfun) (POINTER, long); + void (*freefun) (POINTER, POINTER); +#else + POINTER (*chunkfun) (); + void (*freefun) (); +#endif + POINTER arg; +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = (int) 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; + } + +#if defined(__STDC__) && __STDC__ + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; +#else + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; +#endif + 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 = chunk->contents; + 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 (h, length) + 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; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + 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; + + /* 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 *)new_chunk->contents)[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++) + new_chunk->contents[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->object_base == old_chunk->contents && ! h->maybe_empty_object) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = new_chunk->contents; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} + +/* 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. */ + +#if defined (__STDC__) && __STDC__ +/* 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, POINTER obj); +#endif + +int +_obstack_allocated_p (h, obj) + struct obstack *h; + POINTER 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 && ((POINTER) lp >= obj || (POINTER) (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 + +/* This function has two names with identical definitions. + This is the first one, called from non-ANSI code. */ + +void +_obstack_free (h, obj) + struct obstack *h; + POINTER 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 && ((POINTER) lp >= obj || (POINTER) (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 (); +} + +/* This function is used from ANSI code. */ + +void +obstack_free (h, obj) + struct obstack *h; + POINTER 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 && ((POINTER) lp >= obj || (POINTER) (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 (); +} + +int +_obstack_memory_used (h) + 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. */ +#ifndef _ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# ifndef _ +# define _(Str) gettext (Str) +# endif +# else +# define _(Str) (Str) +# endif +#endif +#if defined _LIBC && defined USE_IN_LIBIO +# include <libio/iolibio.h> +# define fputs(s, f) _IO_fputs (s, f) +#endif + +static void +print_and_abort () +{ + fputs (_("memory exhausted"), stderr); + fputc ('\n', stderr); + exit (obstack_exit_failure); +} + +#if 0 +/* These are now turned off because the applications do not use it + and it uses bcopy via obstack_grow, which causes trouble on sysV. */ + +/* Now define the functional versions of the obstack macros. + Define them to simply use the corresponding macros to do the job. */ + +#if defined (__STDC__) && __STDC__ +/* These function definitions do not work with non-ANSI preprocessors; + they won't pass through the macro names in parentheses. */ + +/* The function names appear in parentheses in order to prevent + the macro-definitions of the names from being expanded there. */ + +POINTER (obstack_base) (obstack) + struct obstack *obstack; +{ + return obstack_base (obstack); +} + +POINTER (obstack_next_free) (obstack) + struct obstack *obstack; +{ + return obstack_next_free (obstack); +} + +int (obstack_object_size) (obstack) + struct obstack *obstack; +{ + return obstack_object_size (obstack); +} + +int (obstack_room) (obstack) + struct obstack *obstack; +{ + return obstack_room (obstack); +} + +int (obstack_make_room) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_make_room (obstack, length); +} + +void (obstack_grow) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow (obstack, pointer, length); +} + +void (obstack_grow0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow0 (obstack, pointer, length); +} + +void (obstack_1grow) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow (obstack, character); +} + +void (obstack_blank) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank (obstack, length); +} + +void (obstack_1grow_fast) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow_fast (obstack, character); +} + +void (obstack_blank_fast) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank_fast (obstack, length); +} + +POINTER (obstack_finish) (obstack) + struct obstack *obstack; +{ + return obstack_finish (obstack); +} + +POINTER (obstack_alloc) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_alloc (obstack, length); +} + +POINTER (obstack_copy) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy (obstack, pointer, length); +} + +POINTER (obstack_copy0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy0 (obstack, pointer, length); +} + +#endif /* __STDC__ */ + +#endif /* 0 */ + +#endif /* !ELIDE_CODE */ diff --git a/lib/m4obstack.h b/lib/m4obstack.h new file mode 100644 index 00000000..4d49ce02 --- /dev/null +++ b/lib/m4obstack.h @@ -0,0 +1,593 @@ +/* obstack.h - object stack macros + Copyright (C) 1988,89,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, 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 use subtraction of (char *) 0 instead of casting to int + because on word-addressable machines a simple cast to int + may ignore the byte-within-word field of the pointer. */ + +#ifndef __PTR_TO_INT +# define __PTR_TO_INT(P) ((P) - (char *) 0) +#endif + +#ifndef __INT_TO_PTR +# define __INT_TO_PTR(P) ((P) + (char *) 0) +#endif + +/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is + defined, as with GNU C, use that; that way we don't pollute the + namespace with <stddef.h>'s symbols. Otherwise, if <stddef.h> is + available, include it and use ptrdiff_t. In traditional C, long is + the best that we can do. */ + +#ifdef __PTRDIFF_TYPE__ +# define PTR_INT_TYPE __PTRDIFF_TYPE__ +#else +# ifdef HAVE_STDDEF_H +# include <stddef.h> +# define PTR_INT_TYPE ptrdiff_t +# else +# define PTR_INT_TYPE long +# endif +#endif + +#if defined _LIBC || defined HAVE_STRING_H +# include <string.h> +# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) +#else +# ifdef memcpy +# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) +# else +# define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N)) +# endif +#endif + +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 */ + PTR_INT_TYPE temp; /* Temporary for some macros. */ + int alignment_mask; /* Mask of alignment for each object. */ +#if defined __STDC__ && __STDC__ + /* 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 */ +#else + struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ + void (*freefun) (); /* User's function to free a chunk. */ + char *extra_arg; /* first arg for chunk alloc/dealloc funcs */ +#endif + 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. */ + +#if defined __STDC__ && __STDC__ +extern void _obstack_newchunk (struct obstack *, int); +extern void _obstack_free (struct obstack *, void *); +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 *); +#else +extern void _obstack_newchunk (); +extern void _obstack_free (); +extern int _obstack_begin (); +extern int _obstack_begin_1 (); +extern int _obstack_memory_used (); +#endif + +#if defined __STDC__ && __STDC__ + +/* Do the function-declarations after the structs + but before defining the macros. */ + +void obstack_init (struct obstack *obstack); + +void * obstack_alloc (struct obstack *obstack, int size); + +void * obstack_copy (struct obstack *obstack, void *address, int size); +void * obstack_copy0 (struct obstack *obstack, void *address, int size); + +void obstack_free (struct obstack *obstack, void *block); + +void obstack_blank (struct obstack *obstack, int size); + +void obstack_grow (struct obstack *obstack, void *data, int size); +void obstack_grow0 (struct obstack *obstack, void *data, int size); + +void obstack_1grow (struct obstack *obstack, int data_char); +void obstack_ptr_grow (struct obstack *obstack, void *data); +void obstack_int_grow (struct obstack *obstack, int data); + +void * obstack_finish (struct obstack *obstack); + +int obstack_object_size (struct obstack *obstack); + +int obstack_room (struct obstack *obstack); +void obstack_make_room (struct obstack *obstack, int size); +void obstack_1grow_fast (struct obstack *obstack, int data_char); +void obstack_ptr_grow_fast (struct obstack *obstack, void *data); +void obstack_int_grow_fast (struct obstack *obstack, int data); +void obstack_blank_fast (struct obstack *obstack, int size); + +void * obstack_base (struct obstack *obstack); +void * obstack_next_free (struct obstack *obstack); +int obstack_alignment_mask (struct obstack *obstack); +int obstack_chunk_size (struct obstack *obstack); +int obstack_memory_used (struct obstack *obstack); + +#endif /* __STDC__ */ + +/* Non-ANSI C cannot really support alternative functions for these macros, + so we do not declare them. */ + +/* 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. */ +#if defined __STDC__ && __STDC__ +extern void (*obstack_alloc_failed_handler) (void); +#else +extern void (*obstack_alloc_failed_handler) (); +#endif + +/* 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) ((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 in + standard C version. */ +#if defined __STDC__ && __STDC__ + +# 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)) + +#else + +# define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) + +# define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) + +# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) ()) (chunkfun), (void (*) ()) (freefun)) + +# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg)) + +# define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun)) + +# define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)()) (newfreefun)) + +#endif + +#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 *__o = (OBSTACK); \ + (unsigned) (__o->next_free - __o->object_base); }) + +# define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack *__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 *__o = (OBSTACK); \ + (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); }) + +# 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); \ + _obstack_memcpy (__o->next_free, (char *) (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); \ + _obstack_memcpy (__o->next_free, (char *) (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); \ + *(__o->next_free)++ = (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 *)); \ + *((void **)__o->next_free)++ = ((void *)datum); \ + (void) 0; }) + +# 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)); \ + *((int *)__o->next_free)++ = ((int)datum); \ + (void) 0; }) + +# define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr) +# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint) + +# 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); \ + __o->next_free += __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; \ + value = (void *) __o1->object_base; \ + if (__o1->next_free == value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ + & ~ (__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 - (h)->chunk->contents == 0) + +/* 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 = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0)) + +# define obstack_grow(h,where,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \ + (h)->next_free += (h)->temp) + +# define obstack_grow0(h,where,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ + _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \ + (h)->next_free += (h)->temp, \ + *((h)->next_free)++ = 0) + +# define obstack_1grow(h,datum) \ +( (((h)->next_free + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + (*((h)->next_free)++ = (datum))) + +# define obstack_ptr_grow(h,datum) \ +( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + (*((char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *) datum))) + +# define obstack_int_grow(h,datum) \ +( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = ((int) datum))) + +# define obstack_ptr_grow_fast(h,aptr) (*((char **) (h)->next_free)++ = (char *) aptr) +# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint) + +# define obstack_blank(h,length) \ +( (h)->temp = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + ((h)->next_free += (h)->temp)) + +# 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 = __PTR_TO_INT ((h)->object_base), \ + (h)->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ + & ~ ((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, \ + __INT_TO_PTR ((h)->temp)) + +# if defined __STDC__ && __STDC__ +# define obstack_free(h,obj) \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) +# else +# define obstack_free(h,obj) \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0))) +# endif + +#endif /* not __GNUC__ or not __STDC__ */ + +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* obstack.h */ diff --git a/lib/m4private.h b/lib/m4private.h new file mode 100644 index 00000000..03542d79 --- /dev/null +++ b/lib/m4private.h @@ -0,0 +1,68 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94, 98 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct token_data { + token_data_type type; + union { + struct { + char *text; +#ifdef ENABLE_CHANGEWORD + char *original_text; +#endif + } u_t; + struct { + builtin_func *func; + boolean traced; + } u_f; + } 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.u_f.func) +#define TOKEN_DATA_FUNC_TRACED(Td) ((Td)->u.u_f.traced) + +/* Redefine the exported function using macro to this faster + macro based version for internal use by the m4 code. */ +#undef M4ARG +#define M4ARG(i) (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "") + +struct symbol +{ + struct symbol *next; + boolean traced; + boolean shadowed; + boolean macro_args; + boolean blind_no_args; + + 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_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)) diff --git a/lib/m4regex.c b/lib/m4regex.c new file mode 100644 index 00000000..36f7faca --- /dev/null +++ b/lib/m4regex.c @@ -0,0 +1,5880 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P1003.2/D11.2, except for some of the + internationalization features.) + Copyright (C) 1993, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* AIX requires this to be the first thing in the file. */ +#if defined _AIX && !defined REGEX_MALLOC + #pragma alloca +#endif + +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef PARAMS +# if defined __GNUC__ || (defined __STDC__ && __STDC__) +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif /* GCC. */ +#endif /* Not PARAMS. */ + +#if defined STDC_HEADERS && !defined emacs +# include <stddef.h> +#else +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +# include <sys/types.h> +#endif + +#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +#if defined _LIBC || WIDE_CHAR_SUPPORT +/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ +# include <wchar.h> +# include <wctype.h> +#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) + +#define btowc __btowc +#endif + +/* This is for other GNU distributions with internationalized messages. */ +#if HAVE_LIBINTL_H || defined _LIBC +# include <libintl.h> +#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 + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +#ifdef emacs + +# include "lisp.h" +# include "buffer.h" +# include "syntax.h" + +#else /* not emacs */ + +/* If we are not linking with Emacs proper, + we can't use the relocating allocator + even if config.h says that we can. */ +# undef REL_ALLOC + +# if defined STDC_HEADERS || defined _LIBC +# include <stdlib.h> +# else +char *malloc (); +char *realloc (); +# endif + +/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. + If nothing else has been done, use the method below. */ +# ifdef INHIBIT_STRING_HEADER +# if !(defined HAVE_BZERO && defined HAVE_BCOPY) +# if !defined bzero && !defined bcopy +# undef INHIBIT_STRING_HEADER +# endif +# endif +# endif + +/* This is the normal way of making sure we have a bcopy and a bzero. + This is used in most programs--a few other programs avoid this + by defining INHIBIT_STRING_HEADER. */ +# ifndef INHIBIT_STRING_HEADER +# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC +# include <string.h> +# ifndef bzero +# ifndef _LIBC +# define bzero(s, n) (memset (s, '\0', n), (s)) +# else +# define bzero(s, n) __bzero (s, n) +# endif +# endif +# else +# include <strings.h> +# ifndef memcmp +# define memcmp(s1, s2, n) bcmp (s1, s2, n) +# endif +# ifndef memcpy +# define memcpy(d, s, n) (bcopy (s, d, n), (d)) +# endif +# endif +# endif + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +# ifndef Sword +# define Sword 1 +# endif + +# ifdef SWITCH_ENUM_BUG +# define SWITCH_ENUM_CAST(x) ((int)(x)) +# else +# define SWITCH_ENUM_CAST(x) (x) +# endif + +/* How many characters in the character set. */ +# define CHAR_SET_SIZE 256 + +# ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +# else /* not SYNTAX_TABLE */ + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void +init_syntax_once () +{ + register int c; + static int done; + + if (done) + return; + + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +# endif /* not SYNTAX_TABLE */ + +# define SYNTAX(c) re_syntax_table[c] + +#endif /* not emacs */ + +/* Get the interface, including the syntax bits. */ +#include <m4regex.h> + +/* isalpha etc. are used for the character classes. */ +#include <ctype.h> + +/* Jim Meyering writes: + + "... Some ctype macros are valid only for character codes that + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + using /bin/cc or gcc but without giving an ansi option). So, all + ctype uses should be through macros like ISPRINT... If + STDC_HEADERS is defined, then autoconf has verified that the ctype + macros don't need to be guarded with references to isascii. ... + Defining isascii to 1 should let any compiler worth its salt + eliminate the && through constant folding." + Solaris defines some of these symbols so we must undefine them first. */ + +#undef ISASCII +#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) +# define ISASCII(c) 1 +#else +# define ISASCII(c) isascii(c) +#endif + +#ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +#else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif +#ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +#else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +#endif + +#undef ISPRINT +#define ISPRINT(c) (ISASCII (c) && isprint (c)) +#define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +#define ISALNUM(c) (ISASCII (c) && isalnum (c)) +#define ISALPHA(c) (ISASCII (c) && isalpha (c)) +#define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +#define ISLOWER(c) (ISASCII (c) && islower (c)) +#define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +#define ISSPACE(c) (ISASCII (c) && isspace (c)) +#define ISUPPER(c) (ISASCII (c) && isupper (c)) +#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +#ifdef _tolower +# define TOLOWER(c) _tolower(c) +#else +# define TOLOWER(c) tolower(c) +#endif + +#ifndef NULL +# define NULL (void *)0 +#endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +#ifdef REGEX_MALLOC + +# define REGEX_ALLOCATE malloc +# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE free + +#else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +# ifndef alloca + +/* Make alloca work the best possible way. */ +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else /* not __GNUC__ */ +# if HAVE_ALLOCA_H +# include <alloca.h> +# endif /* HAVE_ALLOCA_H */ +# endif /* not __GNUC__ */ + +# endif /* not alloca */ + +# define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +# define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + memcpy (destination, source, osize)) + +/* No need to do anything to free, after alloca. */ +# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ + +#endif /* not REGEX_MALLOC */ + +/* Define how to allocate the failure stack. */ + +#if defined REL_ALLOC && defined REGEX_MALLOC + +# define REGEX_ALLOCATE_STACK(size) \ + r_alloc (&failure_stack_ptr, (size)) +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ + r_re_alloc (&failure_stack_ptr, (nsize)) +# define REGEX_FREE_STACK(ptr) \ + r_alloc_free (&failure_stack_ptr) + +#else /* not using relocating allocator */ + +# ifdef REGEX_MALLOC + +# define REGEX_ALLOCATE_STACK malloc +# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE_STACK free + +# else /* not REGEX_MALLOC */ + +# define REGEX_ALLOCATE_STACK alloca + +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ + REGEX_REALLOCATE (source, osize, nsize) +/* No need to explicitly free anything. */ +# define REGEX_FREE_STACK(arg) + +# endif /* not REGEX_MALLOC */ +#endif /* not using relocating allocator */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +#define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define RETALLOC_IF(addr, n, t) \ + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) +#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +#define BYTEWIDTH 8 /* In bits. */ + +#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +#undef MAX +#undef MIN +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +#define false 0 +#define true 1 + +static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop)); + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. */ + +typedef enum +{ + no_op = 0, + + /* Succeed right away--no more backtracking. */ + succeed, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn, + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +#ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +#endif /* emacs */ +} re_opcode_t; + +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ + +#define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ + +#define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += 2; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ + +#define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) + +#ifdef DEBUG +static void extract_number _RE_ARGS ((int *dest, unsigned char *source)); +static void +extract_number (dest, source) + int *dest; + unsigned char *source; +{ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +} + +# ifndef EXTRACT_MACROS /* To debug the macros. */ +# undef EXTRACT_NUMBER +# define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) +# endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += 2; \ + } while (0) + +#ifdef DEBUG +static void extract_number_and_incr _RE_ARGS ((int *destination, + unsigned char **source)); +static void +extract_number_and_incr (destination, source) + int *destination; + unsigned char **source; +{ + extract_number (destination, *source); + *source += 2; +} + +# ifndef EXTRACT_MACROS +# undef EXTRACT_NUMBER_AND_INCR +# define EXTRACT_NUMBER_AND_INCR(dest, src) \ + extract_number_and_incr (&dest, &src) +# endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +#ifdef DEBUG + +/* We use standard I/O for debugging. */ +# include <stdio.h> + +/* It is useful to test things that ``must'' be true when debugging. */ +# include <assert.h> + +static int debug; + +# define DEBUG_STATEMENT(e) e +# define DEBUG_PRINT1(x) if (debug) printf (x) +# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) print_partial_compiled_pattern (s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) print_double_string (w, s1, sz1, s2, sz2) + + +/* Print the fastmap in human-readable form. */ + +void +print_fastmap (fastmap) + char *fastmap; +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + putchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + putchar (i - 1); + } + } + } + putchar ('\n'); +} + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +print_partial_compiled_pattern (start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p1; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + printf ("%d:\t", p - start); + + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + putchar (*p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%d", mcnt, *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%d", mcnt, *p++); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c, last = -100; + register int in_range = 0; + + printf ("/charset [%s", + (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); + + assert (p + *p < pend); + + for (c = 0; c < 256; c++) + if (c / 8 < *p + && (p[1 + (c/8)] & (1 << (c % 8)))) + { + /* Are we starting a range? */ + if (last + 1 == c && ! in_range) + { + putchar ('-'); + in_range = 1; + } + /* Have we broken a range? */ + else if (last + 1 != c && in_range) + { + putchar (last); + in_range = 0; + } + + if (! in_range) + putchar (c); + + last = c; + } + + if (in_range) + putchar (last); + + putchar (']'); + + p += 1 + *p; + } + break; + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_jump to %d", p + mcnt - start); + break; + + case on_failure_keep_string_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_keep_string_jump to %d", p + mcnt - start); + break; + + case dummy_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/dummy_failure_jump to %d", p + mcnt - start); + break; + + case push_dummy_failure: + printf ("/push_dummy_failure"); + break; + + case maybe_pop_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/maybe_pop_jump to %d", p + mcnt - start); + break; + + case pop_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/pop_failure_jump to %d", p + mcnt - start); + break; + + case jump_past_alt: + extract_number_and_incr (&mcnt, &p); + printf ("/jump_past_alt to %d", p + mcnt - start); + break; + + case jump: + extract_number_and_incr (&mcnt, &p); + printf ("/jump to %d", p + mcnt - start); + break; + + case succeed_n: + extract_number_and_incr (&mcnt, &p); + p1 = p + mcnt; + extract_number_and_incr (&mcnt2, &p); + printf ("/succeed_n to %d, %d times", p1 - start, mcnt2); + break; + + case jump_n: + extract_number_and_incr (&mcnt, &p); + p1 = p + mcnt; + extract_number_and_incr (&mcnt2, &p); + printf ("/jump_n to %d, %d times", p1 - start, mcnt2); + break; + + case set_number_at: + extract_number_and_incr (&mcnt, &p); + p1 = p + mcnt; + extract_number_and_incr (&mcnt2, &p); + printf ("/set_number_at location %d to %d", p1 - start, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + +# ifdef emacs + case before_dot: + printf ("/before_dot"); + break; + + case at_dot: + printf ("/at_dot"); + break; + + case after_dot: + printf ("/after_dot"); + break; + + case syntaxspec: + printf ("/syntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; + + case notsyntaxspec: + printf ("/notsyntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; +# endif /* emacs */ + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + + putchar ('\n'); + } + + printf ("%d:\tend of pattern.\n", p - start); +} + + +void +print_compiled_pattern (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); + printf ("%ld bytes used/%ld bytes allocated.\n", + bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + + printf ("re_nsub: %d\t", bufp->re_nsub); + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %lx\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +print_double_string (where, string1, size1, string2, size2) + const char *where; + const char *string1; + const char *string2; + int size1; + int size2; +{ + int this_char; + + if (where == NULL) + printf ("(null)"); + else + { + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + putchar (string1[this_char]); + + where = string2; + } + + for (this_char = where - string2; this_char < size2; this_char++) + putchar (string2[this_char]); + } +} + +void +printchar (c) + int c; +{ + putc (c, stderr); +} + +#else /* not DEBUG */ + +# undef assert +# define assert(e) + +# define DEBUG_STATEMENT(e) +# define DEBUG_PRINT1(x) +# define DEBUG_PRINT2(x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +#endif /* not DEBUG */ + +/* 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; +#ifdef DEBUG + if (syntax & RE_DEBUG) + debug = 1; + else if (debug) /* was on but now is not */ + debug = 0; +#endif /* DEBUG */ + return ret; +} +#ifdef _LIBC +weak_alias (__re_set_syntax, re_set_syntax) +#endif + +/* 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 + }; + +/* Avoiding alloca during matching, to placate r_alloc. */ + +/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the + searching and matching functions should not call alloca. On some + systems, alloca is implemented in terms of malloc, and if we're + using the relocating allocator routines, then malloc could cause a + relocation, which might (if the strings being searched are in the + ralloc heap) shift the data out from underneath the regexp + routines. + + Here's another reason to avoid allocation: Emacs + processes input from X in a signal handler; processing X input may + call malloc; if input arrives while a matching routine is calling + malloc, then we're scrod. But Emacs can't just block input while + calling matching routines; then we don't notice interrupts when + they come in. So, Emacs blocks input around all regexp calls + except the matching calls, which it leaves unprotected, in the + faith that they will not malloc. */ + +/* Normally, this is fine. */ +#define MATCH_MAY_ALLOCATE + +/* When using GNU C, we are not REALLY using the C alloca, no matter + what config.h may say. So don't take precautions for it. */ +#ifdef __GNUC__ +# undef C_ALLOCA +#endif + +/* The match routines may not allocate if (1) they would do it with malloc + and (2) it's not safe for them to use malloc. + Note that if REL_ALLOC is defined, matching would not use malloc for the + failure stack, but we would still use it for the register vectors; + so REL_ALLOC should not affect this. */ +#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs +# undef MATCH_MAY_ALLOCATE +#endif + + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE_STACK. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +# define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_ITEMS items each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ + +#ifdef INT_IS_16BIT + +# if defined MATCH_MAY_ALLOCATE +/* 4400 was enough to cause a crash on Alpha OSF/1, + whose default stack limit is 2mb. */ +long int re_max_failures = 4000; +# else +long int re_max_failures = 2000; +# endif + +union fail_stack_elt +{ + unsigned char *pointer; + long int integer; +}; + +typedef union fail_stack_elt fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned long int size; + unsigned long int avail; /* Offset of next open position. */ +} fail_stack_type; + +#else /* not INT_IS_16BIT */ + +# if defined MATCH_MAY_ALLOCATE +/* 4400 was enough to cause a crash on Alpha OSF/1, + whose default stack limit is 2mb. */ +int re_max_failures = 20000; +# else +int re_max_failures = 2000; +# endif + +union fail_stack_elt +{ + unsigned char *pointer; + int integer; +}; + +typedef union fail_stack_elt fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#endif /* INT_IS_16BIT */ + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) + + +/* Define macros to initialize and free the failure stack. + Do `return -2' if the alloc fails. */ + +#ifdef MATCH_MAY_ALLOCATE +# define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) + +# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) +#else +# define INIT_FAIL_STACK() \ + do { \ + fail_stack.avail = 0; \ + } while (0) + +# define RESET_FAIL_STACK() +#endif + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE_STACK requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE_STACK ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push pointer POINTER on FAIL_STACK. + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ + ? 0 \ + : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ + 1)) + +/* Push a pointer value onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_POINTER(item) \ + fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item) + +/* This pushes an integer-valued item onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_INT(item) \ + fail_stack.stack[fail_stack.avail++].integer = (item) + +/* Push a fail_stack_elt_t value onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ELT(item) \ + fail_stack.stack[fail_stack.avail++] = (item) + +/* These three POP... operations complement the three PUSH... operations. + All assume that `fail_stack' is nonempty. */ +#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer +#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer +#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +# define DEBUG_PUSH PUSH_FAILURE_INT +# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () +#else +# define DEBUG_PUSH(item) +# define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' + be declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + /* Can't be int, since there is not a shred of a guarantee that int \ + is wide enough to hold a value of something to which pointer can \ + be assigned */ \ + active_reg_t this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + if (1) \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ + PUSH_FAILURE_POINTER (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ + PUSH_FAILURE_POINTER (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: %p\n ", \ + reg_info[this_reg].word.pointer); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ELT (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ + PUSH_FAILURE_INT (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ + PUSH_FAILURE_INT (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_POINTER (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_POINTER (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +# define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +/* We used to use (num_regs - 1), which is the number of registers + this regexp will save; but that was changed to 5 + to avoid stack overflow for a regexp with lots of parens. */ +#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + (((0 \ + ? 0 : highest_active_reg - lowest_active_reg + 1) \ + * NUM_REG_ITEMS) \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (unsigned failure_id;) \ + active_reg_t this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_POINTER (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string %p: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (active_reg_t) POP_FAILURE_INT (); \ + DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ + \ + low_reg = (active_reg_t) POP_FAILURE_INT (); \ + DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ + \ + if (1) \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ELT (); \ + DEBUG_PRINT2 (" info: %p\n", \ + reg_info[this_reg].word.pointer); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ + } \ + else \ + { \ + for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ + { \ + reg_info[this_reg].word.integer = 0; \ + regend[this_reg] = 0; \ + regstart[this_reg] = 0; \ + } \ + highest_active_reg = high_reg; \ + } \ + \ + set_regs_matched_done = 0; \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + + + +/* Structure for per-register (a.k.a. per-group) information. + Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ + + +/* Declarations and macros for re_match_2. */ + +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + if (!set_regs_matched_done) \ + { \ + active_reg_t r; \ + set_regs_matched_done = 1; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + } \ + while (0) + +/* Registers are set to a sentinel when they haven't yet matched. */ +static char reg_unset_dummy; +#define REG_UNSET_VALUE (®_unset_dummy) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + +/* Subroutine declarations and macros for regex_compile. */ + +static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp)); +static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg)); +static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, + int arg1, int arg2)); +static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, + int arg, unsigned char *end)); +static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, + int arg1, int arg2, unsigned char *end)); +static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p, + reg_syntax_t syntax)); +static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend, + reg_syntax_t syntax)); +static reg_errcode_t compile_range _RE_ARGS ((const char **p_ptr, + const char *pend, + char *translate, + reg_syntax_t syntax, + unsigned char *b)); + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +#ifndef PATFETCH +# define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = (unsigned char) translate[c]; \ + } while (0) +#endif + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +#define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +#ifndef TRANSLATE +# define TRANSLATE(d) \ + (translate ? (char) translate[(unsigned char) (d)] : (d)) +#endif + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 32 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ + EXTEND_BUFFER () + +/* Make sure we have one more byte of buffer space and then add C to it. */ +#define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (unsigned char) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +#define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +#define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + *b++ = (unsigned char) (c3); \ + } while (0) + + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +#define STORE_JUMP(op, loc, to) \ + store_op1 (op, loc, (int) ((to) - (loc) - 3)) + +/* Likewise, for a two-argument jump. */ +#define STORE_JUMP2(op, loc, to, arg) \ + store_op2 (op, loc, (int) ((to) - (loc) - 3), arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP(op, loc, to) \ + insert_op1 (op, loc, (int) ((to) - (loc) - 3), b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP2(op, loc, to, arg) \ + insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b) + + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +/* Any other compiler which, like MSC, has allocation limit below 2^16 + bytes will have to use approach similar to what was done below for + MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up + reallocating to 0 bytes. Such thing is not going to work too well. + You have been warned!! */ +#if defined _MSC_VER && !defined WIN32 +/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. + The REALLOC define eliminates a flurry of conversion warnings, + but is not required. */ +# define MAX_BUF_SIZE 65500L +# define REALLOC(p,s) realloc ((p), (size_t) (s)) +#else +# define MAX_BUF_SIZE (1L << 16) +# define REALLOC(p,s) realloc ((p), (s)) +#endif + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER() \ + do { \ + unsigned char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + + +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +#define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +/* int may be not enough when sizeof(int) == 2. */ +typedef long pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +#define INIT_COMPILE_STACK_SIZE 32 + +#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + + +/* Set the bit for character C in a list. */ +#define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) + + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +#if defined _LIBC || WIDE_CHAR_SUPPORT +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif +#else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +#endif + +#ifndef MATCH_MAY_ALLOCATE + +/* If we cannot allocate large objects within re_match_2_internal, + we make the fail stack and register vectors global. + The fail stack, we grow to the maximum size when a regexp + is compiled. + The register vectors, we adjust in size each time we + compile a regexp, according to the number of registers it needs. */ + +static fail_stack_type fail_stack; + +/* Size with which the following vectors are currently allocated. + That is so we can make them bigger as needed, + but never make them smaller. */ +static int regs_allocated_size; + +static const char ** regstart, ** regend; +static const char ** old_regstart, ** old_regend; +static const char **best_regstart, **best_regend; +static register_info_type *reg_info; +static const char **reg_dummy; +static register_info_type *reg_info_dummy; + +/* Make the register vectors big enough for NUM_REGS registers, + but don't make them smaller. */ + +static +regex_grow_registers (num_regs) + int num_regs; +{ + if (num_regs > regs_allocated_size) + { + RETALLOC_IF (regstart, num_regs, const char *); + RETALLOC_IF (regend, num_regs, const char *); + RETALLOC_IF (old_regstart, num_regs, const char *); + RETALLOC_IF (old_regend, num_regs, const char *); + RETALLOC_IF (best_regstart, num_regs, const char *); + RETALLOC_IF (best_regend, num_regs, const char *); + RETALLOC_IF (reg_info, num_regs, register_info_type); + RETALLOC_IF (reg_dummy, num_regs, const char *); + RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); + + regs_allocated_size = num_regs; + } +} + +#endif /* not MATCH_MAY_ALLOCATE */ + +static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type + compile_stack, + regnum_t regnum)); + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +/* Return, freeing storage we allocated. */ +#define FREE_STACK_RETURN(value) \ + return (free (compile_stack.stack), value) + +static reg_errcode_t +regex_compile (pattern, size, syntax, bufp) + const char *pattern; + size_t size; + reg_syntax_t syntax; + struct re_pattern_buffer *bufp; +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register unsigned char c, c1; + + /* A random temporary spot in PATTERN. */ + const char *p1; + + /* Points to the end of the buffer, where we should append. */ + register unsigned char *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ + const char *p = pattern; + const char *pend = pattern + size; + + /* How to translate the characters in the pattern. */ + RE_TRANSLATE_TYPE translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + unsigned char *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + unsigned char *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + unsigned char *begalt; + + /* Place in the uncompiled pattern (i.e., the {) to + which to go back if the interval is invalid. */ + const char *beg_interval; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + unsigned char *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + putchar (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + return REG_ESPACE; + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined emacs && !defined SYNTAX_TABLE + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* 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. */ + RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); + } + if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE); + + bufp->allocated = INIT_BUF_SIZE; + } + + begalt = b = bufp->buffer; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || at_begline_loc_p (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || at_endline_loc_p (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + FREE_STACK_RETURN (REG_BADRPT); + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (3); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - 3); + + /* We've added more stuff to the buffer. */ + b += 3; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 3); + pending_exact = 0; + b += 3; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); + b += 3; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + SET_LIST_BIT (c1); + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + FREE_STACK_RETURN (REG_ERANGE); + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == ':' && *p == ']') || p == pend) + break; + if (c1 < CHAR_CLASS_MAX_LENGTH) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and `:]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { +#if defined _LIBC || WIDE_CHAR_SUPPORT + boolean is_lower = STREQ (str, "lower"); + boolean is_upper = STREQ (str, "upper"); + wctype_t wt; + int ch; + + wt = IS_CHAR_CLASS (str); + if (wt == 0) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) + { +# ifdef _LIBC + if (__iswctype (__btowc (ch), wt)) + SET_LIST_BIT (ch); +# else + if (iswctype (btowc (ch), wt)) + SET_LIST_BIT (ch); +# endif + + if (translate && (is_upper || is_lower) + && (ISUPPER (ch) || ISLOWER (ch))) + SET_LIST_BIT (ch); + } + + had_char_class = true; +#else + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + /* This was split into 3 if's to + avoid an arbitrary limit in some compiler. */ + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch))) + SET_LIST_BIT (ch); + if ( (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch))) + SET_LIST_BIT (ch); + if ( (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + if ( translate && (is_upper || is_lower) + && (ISUPPER (ch) || ISLOWER (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; +#endif /* libc || wctype.h */ + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + FREE_STACK_RETURN (REG_ERPAREN); + } + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + FREE_STACK_RETURN (REG_ERPAREN); + } + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + unsigned char *inner_group_loc + = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (on_failure_jump, begalt, b + 6); + pending_exact = 0; + b += 3; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (3); + b += 3; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + || (p - 2 == pattern && p == pend)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + beg_interval = p - 1; + + if (p == pend) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + FREE_STACK_RETURN (REG_EBRACE); + } + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + FREE_STACK_RETURN (REG_BADBR); + } + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\') FREE_STACK_RETURN (REG_EBRACE); + + PATFETCH (c); + } + + if (c != '}') + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + FREE_STACK_RETURN (REG_BADBR); + } + + /* We just parsed a valid interval. */ + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + FREE_STACK_RETURN (REG_BADRPT); + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + INSERT_JUMP (jump, laststart, b + 3); + b += 3; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at <jump count> <upper bound> + set_number_at <succeed_n count> <lower bound> + succeed_n <after jump addr> <succeed_n count> + <body of loop> + jump_n <succeed_n addr> <jump count> + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 10 + (upper_bound > 1) * 10; + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 5 + (upper_bound > 1) * 5, + lower_bound); + b += 5; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + insert_op2 (set_number_at, laststart, 5, lower_bound, b); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op2 (set_number_at, laststart, b - laststart, + upper_bound - 1, b); + b += 5; + } + } + pending_exact = 0; + beg_interval = NULL; + } + break; + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + assert (beg_interval); + p = beg_interval; + beg_interval = NULL; + + /* normal_char and normal_backslash need `c'. */ + PATFETCH (c); + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (p > pattern && p[-1] == '\\') + goto normal_backslash; + } + goto normal_char; + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordbeg); + break; + + case '>': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordend); + break; + + case 'b': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordbound); + break; + + case 'B': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (notwordbound); + break; + + case '`': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (begbuf); + break; + + case '\'': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (endbuf); + 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) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + FREE_STACK_RETURN (REG_ESUBREG); + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, (regnum_t) c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + + BUF_PUSH_2 (exactn, 0); + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + FREE_STACK_RETURN (REG_EPAREN); + + /* If we don't want backtracking, force success + the first time we reach the end of the compiled pattern. */ + if (syntax & RE_NO_POSIX_BACKTRACKING) + BUF_PUSH (succeed); + + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ + bufp->used = b - bufp->buffer; + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: \n"); + print_compiled_pattern (bufp); + } +#endif /* DEBUG */ + +#ifndef MATCH_MAY_ALLOCATE + /* Initialize the failure stack to the largest possible stack. This + isn't necessary unless we're trying to avoid calling alloca in + the search and match routines. */ + { + int num_regs = bufp->re_nsub + 1; + + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size + is strictly greater than re_max_failures, the largest possible stack + is 2 * re_max_failures failure points. */ + if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) + { + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); + +# ifdef emacs + if (! fail_stack.stack) + fail_stack.stack + = (fail_stack_elt_t *) xmalloc (fail_stack.size + * sizeof (fail_stack_elt_t)); + else + fail_stack.stack + = (fail_stack_elt_t *) xrealloc (fail_stack.stack, + (fail_stack.size + * sizeof (fail_stack_elt_t))); +# else /* not emacs */ + if (! fail_stack.stack) + fail_stack.stack + = (fail_stack_elt_t *) malloc (fail_stack.size + * sizeof (fail_stack_elt_t)); + else + fail_stack.stack + = (fail_stack_elt_t *) realloc (fail_stack.stack, + (fail_stack.size + * sizeof (fail_stack_elt_t))); +# endif /* not emacs */ + } + + regex_grow_registers (num_regs); + } +#endif /* not MATCH_MAY_ALLOCATE */ + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ + +static void +store_op1 (op, loc, arg) + re_opcode_t op; + unsigned char *loc; + int arg; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +store_op2 (op, loc, arg1, arg2) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 3, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ + +static void +insert_op1 (op, loc, arg, end) + re_opcode_t op; + unsigned char *loc; + int arg; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 3; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op1 (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +insert_op2 (op, loc, arg1, arg2, end) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 5; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op2 (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +at_begline_loc_p (pattern, p, syntax) + const char *pattern, *p; + reg_syntax_t syntax; +{ + const char *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +at_endline_loc_p (p, pend, syntax) + const char *p, *pend; + reg_syntax_t syntax; +{ + const char *next = p; + boolean next_backslash = *next == '\\'; + const char *next_next = p + 1 < pend ? p + 1 : 0; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack (compile_stack, regnum) + compile_stack_type compile_stack; + regnum_t regnum; +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} + + +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +compile_range (p_ptr, pend, translate, syntax, b) + const char **p_ptr, *pend; + RE_TRANSLATE_TYPE translate; + reg_syntax_t syntax; + unsigned char *b; +{ + unsigned this_char; + + const char *p = *p_ptr; + unsigned int range_start, range_end; + + if (p == pend) + return REG_ERANGE; + + /* Even though the pattern is a signed `char *', we need to fetch + with unsigned char *'s; if the high bit of the pattern character + is set, the range endpoints will be negative if we fetch using a + signed char *. + + We also want to fetch the endpoints without translating them; the + appropriate translation is done in the bit-setting loop below. */ + /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */ + range_start = ((const unsigned char *) p)[-2]; + range_end = ((const unsigned char *) p)[0]; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* If the start is after the end, the range is empty. */ + if (range_start > range_end) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- the range is inclusive, so if `range_end' == 0xff + (assuming 8-bit characters), we would otherwise go into an infinite + loop, since all characters <= 0xff. */ + for (this_char = range_start; this_char <= range_end; this_char++) + { + SET_LIST_BIT (TRANSLATE (this_char)); + } + + return REG_NOERROR; +} + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +int +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + int j, k; +#ifdef MATCH_MAY_ALLOCATE + fail_stack_type fail_stack; +#endif +#ifndef REGEX_MALLOC + char *destination; +#endif + + register char *fastmap = bufp->fastmap; + unsigned char *pattern = bufp->buffer; + unsigned char *p = pattern; + register unsigned char *pend = pattern + bufp->used; + +#ifdef REL_ALLOC + /* This holds the pointer to the failure stack, when + it is allocated relocatably. */ + fail_stack_elt_t *failure_stack_ptr; +#endif + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (1) + { + if (p == pend || *p == succeed) + { + /* We have reached the (effective) end of pattern. */ + if (!FAIL_STACK_EMPTY ()) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail].pointer; + + continue; + } + else + break; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + goto done; + + + /* Following are the cases which match a character. These end + with `break'. */ + + case exactn: + fastmap[p[1]] = 1; + break; + + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + + + case anychar: + { + int fastmap_newline = fastmap['\n']; + + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = fastmap_newline; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + goto done; + + /* Otherwise, have to check alternative paths. */ + break; + } + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1].pointer == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + { + RESET_FAIL_STACK (); + return -2; + } + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += 2; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 4; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + + done: + RESET_FAIL_STACK (); + return 0; +} /* re_compile_fastmap */ +#ifdef _LIBC +weak_alias (__re_compile_fastmap, re_compile_fastmap) +#endif + +/* 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; + unsigned 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 = (regoff_t *) 0; + } +} +#ifdef _LIBC +weak_alias (__re_set_registers, re_set_registers) +#endif + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search (bufp, string, size, startpos, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, startpos, range; + struct re_registers *regs; +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} +#ifdef _LIBC +weak_alias (__re_search, re_search) +#endif + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int startpos; + int range; + struct re_registers *regs; + int stop; +{ + int val; + register char *fastmap = bufp->fastmap; + register RE_TRANSLATE_TYPE translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. + Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ + if (endpos < 0) + range = 0 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && range > 0 + && ((re_opcode_t) bufp->buffer[0] == begbuf + /* `begline' is like `begbuf' if it cannot match at newlines. */ + || ((re_opcode_t) bufp->buffer[0] == begline + && !bufp->newline_anchor))) + { + if (startpos > 0) + return -1; + else + range = 1; + } + +#ifdef emacs + /* In a forward search for something that starts with \=. + don't keep searching past point. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) + { + range = PT - startpos; + if (range <= 0) + return -1; + } +#endif /* emacs */ + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register char c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + return -1; + + val = re_match_2_internal (bufp, string1, size1, string2, size2, + startpos, regs, stop); +#ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +#endif + + if (val >= 0) + return startpos; + + if (val == -2) + return -2; + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} /* re_search_2 */ +#ifdef _LIBC +weak_alias (__re_search_2, re_search_2) +#endif + +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) + +/* Disabled due to a compiler bug -- see comment at case wordbound */ +#if 0 +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) +#endif + +/* Free everything we malloc. */ +#ifdef MATCH_MAY_ALLOCATE +# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL +# define FREE_VARIABLES() \ + do { \ + REGEX_FREE_STACK (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +#else +# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ +#endif /* not MATCH_MAY_ALLOCATE */ + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match (bufp, string, size, pos, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, pos; + struct re_registers *regs; +{ + int result = re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size); +# ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +# endif + return result; +} +# ifdef _LIBC +weak_alias (__re_match, re_match) +# endif +#endif /* not emacs */ + +static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p, + unsigned char *end, + register_info_type *reg_info)); +static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p, + unsigned char *end, + register_info_type *reg_info)); +static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p, + unsigned char *end, + register_info_type *reg_info)); +static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2, + int len, char *translate)); + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + int result = re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop); +#ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +#endif + return result; +} +#ifdef _LIBC +weak_alias (__re_match_2, re_match_2) +#endif + +/* This is a separate function so that we can force an alloca cleanup + afterwards. */ +static int +re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + /* General temporaries. */ + int mcnt; + unsigned char *p1; + + /* Just past the end of the corresponding string. */ + const char *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const char *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const char *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ + unsigned char *p = bufp->buffer; + register unsigned char *pend = p + bufp->used; + + /* Mark the opcode just after a start_memory, so we can test for an + empty subpattern when we get to the stop_memory. */ + unsigned char *just_past_start_mem = 0; + + /* We use this to map every character in the string. */ + RE_TRANSLATE_TYPE translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + fail_stack_type fail_stack; +#endif +#ifdef DEBUG + static unsigned failure_id; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + +#ifdef REL_ALLOC + /* This holds the pointer to the failure stack, when + it is allocated relocatably. */ + fail_stack_elt_t *failure_stack_ptr; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + size_t num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; + active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **regstart, **regend; +#endif + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **old_regstart, **old_regend; +#endif + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + register_info_type *reg_info; +#endif + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **best_regstart, **best_regend; +#endif + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const char *match_end = NULL; + + /* This helps SET_REGS_MATCHED avoid doing redundant work. */ + int set_regs_matched_done = 0; + + /* Used when we pop values we don't care about. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **reg_dummy; + register_info_type *reg_info_dummy; +#endif + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + +#ifdef MATCH_MAY_ALLOCATE + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const char *); + regend = REGEX_TALLOC (num_regs, const char *); + old_regstart = REGEX_TALLOC (num_regs, const char *); + old_regend = REGEX_TALLOC (num_regs, const char *); + best_regstart = REGEX_TALLOC (num_regs, const char *); + best_regend = REGEX_TALLOC (num_regs, const char *); + reg_info = REGEX_TALLOC (num_regs, register_info_type); + reg_dummy = REGEX_TALLOC (num_regs, const char *); + reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (register_info_type *) NULL; + } +#endif /* MATCH_MAY_ALLOCATE */ + + /* The starting position is bogus. */ + if (pos < 0 || pos > size1 + size2) + { + FREE_VARIABLES (); + return -1; + } + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } + + DEBUG_PRINT1 ("The compiled pattern is:\n"); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { +#ifdef _LIBC + DEBUG_PRINT2 ("\n%p: ", p); +#else + DEBUG_PRINT2 ("\n0x%x: ", p); +#endif + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + /* 1 if this match ends in the same string (string1 or string2) + as the best previous match. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + /* 1 if this match is the best seen so far. */ + boolean best_match_p; + + /* AIX compiler got confused when this was combined + with the previous declaration. */ + if (same_str_p) + best_match_p = d > match_end; + else + best_match_p = !MATCHING_IN_FIRST_STRING; + + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + + /* If exceeds best match so far, save it. */ + if (!best_regs_set || best_match_p) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. And if + last match is real best match, don't restore second + best one. */ + else if (best_regs_set && !best_match_p) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + succeed_label: + DEBUG_PRINT1 ("Accepting match.\n"); + + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + { + FREE_VARIABLES (); + return -2; + } + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->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 (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + { + FREE_VARIABLES (); + return -2; + } + } + } + else + { + /* These braces fend off a "empty body in an else-statement" + warning under GCC when assert expands to nothing. */ + assert (bufp->regs_allocated == REGS_FIXED); + } + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); + mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + FREE_VARIABLES (); + return mcnt; + } + + /* Otherwise match next pattern command. */ + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + case succeed: + DEBUG_PRINT1 ("EXECUTING succeed.\n"); + goto succeed_label; + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); + if ((unsigned char) translate[(unsigned char) *d++] + != (unsigned char) *p++) + goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (char) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", *d); + d++; + break; + + + case charset: + case charset_not: + { + register unsigned char c; + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ + + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Clear this whenever we change the register activity status. */ + set_regs_matched_done = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + just_past_start_mem = p; + + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* Clear this whenever we change the register activity status. */ + set_regs_matched_done = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + unsigned char r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || just_past_start_mem == p - 1) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += 2; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); + r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if (old_regend[r] >= regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: + { + register const char *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate (d, d2, mcnt, translate) + : memcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + + /* Do this because we've match some characters. */ + SET_REGS_MATCHED (); + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); +#else + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); +#endif + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); +#else + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); +#endif + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(zz\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. + If what follows this loop is a ...+ construct, + look at what begins its body, since we will have to + match at least one of that. */ + while (1) + { + if (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; + else if (p2 + 6 < pend + && (re_opcode_t) *p2 == dummy_failure_jump) + p2 += 6; + else + break; + } + + p1 = p + mcnt; + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + + if ((re_opcode_t) p1[3] == exactn && p1[5] != c) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned char) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + else if ((re_opcode_t) *p2 == charset) + { + /* We win if the first character of the loop is not part + of the charset. */ + if ((re_opcode_t) p1[3] == exactn + && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] + && (p2[2 + p1[5] / BYTEWIDTH] + & (1 << (p1[5] % BYTEWIDTH))))) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + + else if ((re_opcode_t) p1[3] == charset_not) + { + int idx; + /* We win if the charset_not inside the loop + lists every character listed in the charset after. */ + for (idx = 0; idx < (int) p2[1]; idx++) + if (! (p2[2 + idx] == 0 + || (idx < (int) p1[4] + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) + break; + + if (idx == p2[1]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + else if ((re_opcode_t) p1[3] == charset) + { + int idx; + /* We win if the charset inside the loop + has no overlap with the one after the loop. */ + for (idx = 0; + idx < (int) p2[1] && idx < (int) p1[4]; + idx++) + if ((p2[2 + idx] & p1[5 + idx]) != 0) + break; + + if (idx == p2[1] || idx == p1[4]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + } + p -= 2; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (unsigned char) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + active_reg_t dummy_low_reg, dummy_high_reg; + unsigned char *pdummy; + const char *sdummy; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + unconditional_jump: +#ifdef _LIBC + DEBUG_PRINT2 ("\n%p: ", p); +#else + DEBUG_PRINT2 ("\n0x%x: ", p); +#endif + /* Note fall through. */ + + /* Unconditionally jump (without popping any failure points). */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ +#ifdef _LIBC + DEBUG_PRINT2 ("(to %p).\n", p); +#else + DEBUG_PRINT2 ("(to 0x%x).\n", p); +#endif + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (NULL, NULL, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (NULL, NULL, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p - 2, mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - 2, mcnt); +#endif + } + else if (mcnt == 0) + { +#ifdef _LIBC + DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", p+2); +#else + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); +#endif + p[2] = (unsigned char) no_op; + p[3] = (unsigned char) no_op; + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + 2, mcnt); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p + 2, mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + 2, mcnt); +#endif + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); +#endif + STORE_NUMBER (p1, mcnt); + break; + } + +#if 0 + /* The DEC Alpha C compiler 3.x generates incorrect code for the + test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of + AT_WORD_BOUNDARY, so this code is disabled. Expanding the + macro and introducing temporary variables works around the bug. */ + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; +#else + case wordbound: + { + boolean prevchar, thischar; + + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) + break; + + prevchar = WORDCHAR_P (d - 1); + thischar = WORDCHAR_P (d); + if (prevchar != thischar) + break; + goto fail; + } + + case notwordbound: + { + boolean prevchar, thischar; + + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) + goto fail; + + prevchar = WORDCHAR_P (d - 1); + thischar = WORDCHAR_P (d); + if (prevchar != thischar) + goto fail; + break; + } +#endif + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) + break; + goto fail; + +#ifdef emacs + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +group_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + /* Point to after the args to the start_memory. */ + unsigned char *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); + + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +alt_match_null_string_p (p, end, reg_info) + unsigned char *p, *end; + register_info_type *reg_info; +{ + int mcnt; + unsigned char *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +common_op_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + boolean ret; + int reg_no; + unsigned char *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = group_match_null_string_p (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += 2; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 4; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 4; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +bcmp_translate (s1, s2, len, translate) + const char *s1, *s2; + register int len; + RE_TRANSLATE_TYPE translate; +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + while (len) + { + if (translate[*p1++] != translate[*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) 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. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern (pattern, length, bufp) + const char *pattern; + size_t length; + struct re_pattern_buffer *bufp; +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* 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. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = regex_compile (pattern, length, re_syntax_options, bufp); + + 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 + +/* 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 below without link errors. */ +weak_function +#endif +re_comp (s) + const char *s; +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return gettext ("No previous regular expression"); + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return (char *) gettext (re_error_msgid + + re_error_msgid_idx[(int) REG_ESPACE]); + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + 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 = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + 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]); +} + + +int +#ifdef _LIBC +weak_function +#endif +re_exec (s) + const char *s; +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} + +#endif /* _REGEX_RE_COMP */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* 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 *preg; + const char *pattern; + int cflags; +{ + reg_errcode_t ret; + reg_syntax_t syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = (char *) malloc (1 << BYTEWIDTH); + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate + = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE + * sizeof (*(RE_TRANSLATE_TYPE)0)); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; + } + else + preg->translate = NULL; + + /* 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); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ + ret = regex_compile (pattern, strlen (pattern), syntax, preg); + + /* 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; + + if (ret == REG_NOERROR && preg->fastmap) + { + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. */ + if (re_compile_fastmap (preg) == -2) + { + /* Some error occured while computing the fastmap, just forget + about it. */ + free (preg->fastmap); + preg->fastmap = NULL; + } + } + + return (int) ret; +} +#ifdef _LIBC +weak_alias (__regcomp, regcomp) +#endif + + +/* 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 *preg; + const char *string; + size_t nmatch; + regmatch_t pmatch[]; + int eflags; +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch * 2, regoff_t); + if (regs.start == NULL) + return (int) REG_NOMATCH; + regs.end = regs.start + nmatch; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} +#ifdef _LIBC +weak_alias (__regexec, regexec) +#endif + + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (errcode, preg, errbuf, errbuf_size) + int errcode; + const regex_t *preg; + char *errbuf; + size_t errbuf_size; +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (int) (sizeof (re_error_msgid_idx) + / sizeof (re_error_msgid_idx[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 (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { +#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 + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (preg) + regex_t *preg; +{ + if (preg->buffer != NULL) + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + if (preg->fastmap != NULL) + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + if (preg->translate != NULL) + free (preg->translate); + preg->translate = NULL; +} +#ifdef _LIBC +weak_alias (__regfree, regfree) +#endif + +#endif /* not emacs */ diff --git a/lib/m4regex.h b/lib/m4regex.h new file mode 100644 index 00000000..d88ab92b --- /dev/null +++ b/lib/m4regex.h @@ -0,0 +1,542 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _REGEX_H +#define _REGEX_H 1 + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* POSIX says that <sys/types.h> must be included (by the caller) before + <regex.h>. */ + +#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS +/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it + should be there. */ +# include <stddef.h> +#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; + +/* 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 \<digit> matches <digit>. + If not set, then \<digit> 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) + +/* 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; + +/* 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)) + +#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) + +/* 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) + +/* 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_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS 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]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +# undef RE_DUP_MAX +#endif +/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ +#define RE_DUP_MAX (0x7fff) + + +/* 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 (REG_EXTENDED << 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 (REG_ICASE << 1) + +/* 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 (REG_NEWLINE << 1) + + +/* 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) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ +#ifdef _XOPEN_SOURCE + REG_ENOSYS = -1, /* This will never happen for this implementation. */ +#endif + + 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, /* Not implemented. */ + 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; + +/* 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. */ + +#ifndef RE_TRANSLATE_TYPE +# define RE_TRANSLATE_TYPE char * +#endif + +struct re_pattern_buffer +{ +/* [[[begin 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 *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long int allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long int used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t 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 *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. */ + RE_TRANSLATE_TYPE 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 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. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned 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 fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the + beginning of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_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 +{ + unsigned num_regs; + regoff_t *start; + regoff_t *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. */ +#ifndef RE_NREGS +# 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. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +# define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +# define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* 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 _RE_ARGS ((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 + _RE_ARGS ((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 _RE_ARGS ((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 int re_search + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, int 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 int re_search_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop)); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs)); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int 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 + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned 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 _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); +# endif +#endif + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern, + int __cflags)); + +extern int regexec _RE_ARGS ((const regex_t *__preg, + const char *__string, size_t __nmatch, + regmatch_t __pmatch[], int __eflags)); + +extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg, + char *__errbuf, size_t __errbuf_size)); + +extern void regfree _RE_ARGS ((regex_t *__preg)); + + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* regex.h */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/lib/obstack.c b/lib/obstack.c new file mode 100644 index 00000000..bf18ddc8 --- /dev/null +++ b/lib/obstack.c @@ -0,0 +1,485 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988, 89, 90, 91, 92, 93, 94 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "obstack.h" + +/* This is just to get __GNU_LIBRARY__ defined. */ +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. 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. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +#if defined (__STDC__) && __STDC__ +#define POINTER void * +#else +#define POINTER char * +#endif + +/* Determine default alignment. */ +struct fooalign {char x; double d;}; +#define DEFAULT_ALIGNMENT \ + ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0)) +/* 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. */ +union fooround {long x; double d;}; +#define 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 non-GNU-C macros copy the obstack into this global variable + to avoid multiple evaluation. */ + +struct obstack *_obstack; + +/* 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)) \ + : (*(h)->chunkfun) ((size))) + +#define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(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, zero if out of memory. + To recover from an out of memory error, + free up some memory, then call this again. */ + +int +_obstack_begin (h, size, alignment, chunkfun, freefun) + struct obstack *h; + int size; + int alignment; + POINTER (*chunkfun) (); + void (*freefun) (); +{ + 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 * (*)()) chunkfun; + h->freefun = 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) + { + h->alloc_failed = 1; + return 0; + } + h->alloc_failed = 0; + h->next_free = h->object_base = chunk->contents; + 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; + return 1; +} + +int +_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) + struct obstack *h; + int size; + int alignment; + POINTER (*chunkfun) (); + void (*freefun) (); + POINTER 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 * (*)()) chunkfun; + h->freefun = 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) + { + h->alloc_failed = 1; + return 0; + } + h->alloc_failed = 0; + h->next_free = h->object_base = chunk->contents; + 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; + 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 (h, length) + struct obstack *h; + int length; +{ + register struct _obstack_chunk* old_chunk = h->chunk; + register struct _obstack_chunk* new_chunk; + register long new_size; + register int obj_size = h->next_free - h->object_base; + register int i; + int already; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + 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) + { + h->alloc_failed = 1; + return; + } + h->alloc_failed = 0; + h->chunk = new_chunk; + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* 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 *)new_chunk->contents)[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++) + new_chunk->contents[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->object_base == old_chunk->contents && ! h->maybe_empty_object) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = new_chunk->contents; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} + +/* 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. */ + +#if defined (__STDC__) && __STDC__ +/* 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, POINTER obj); +#endif + +int +_obstack_allocated_p (h, obj) + struct obstack *h; + POINTER 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 && ((POINTER)lp >= obj || (POINTER)(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 + +/* This function has two names with identical definitions. + This is the first one, called from non-ANSI code. */ + +void +_obstack_free (h, obj) + struct obstack *h; + POINTER 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 && ((POINTER)lp >= obj || (POINTER)(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 (); +} + +/* This function is used from ANSI code. */ + +void +obstack_free (h, obj) + struct obstack *h; + POINTER 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 && ((POINTER)lp >= obj || (POINTER)(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 (); +} + +#if 0 +/* These are now turned off because the applications do not use it + and it uses bcopy via obstack_grow, which causes trouble on sysV. */ + +/* Now define the functional versions of the obstack macros. + Define them to simply use the corresponding macros to do the job. */ + +#if defined (__STDC__) && __STDC__ +/* These function definitions do not work with non-ANSI preprocessors; + they won't pass through the macro names in parentheses. */ + +/* The function names appear in parentheses in order to prevent + the macro-definitions of the names from being expanded there. */ + +POINTER (obstack_base) (obstack) + struct obstack *obstack; +{ + return obstack_base (obstack); +} + +POINTER (obstack_next_free) (obstack) + struct obstack *obstack; +{ + return obstack_next_free (obstack); +} + +int (obstack_object_size) (obstack) + struct obstack *obstack; +{ + return obstack_object_size (obstack); +} + +int (obstack_room) (obstack) + struct obstack *obstack; +{ + return obstack_room (obstack); +} + +void (obstack_grow) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow (obstack, pointer, length); +} + +void (obstack_grow0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow0 (obstack, pointer, length); +} + +void (obstack_1grow) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow (obstack, character); +} + +void (obstack_blank) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank (obstack, length); +} + +void (obstack_1grow_fast) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow_fast (obstack, character); +} + +void (obstack_blank_fast) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank_fast (obstack, length); +} + +POINTER (obstack_finish) (obstack) + struct obstack *obstack; +{ + return obstack_finish (obstack); +} + +POINTER (obstack_alloc) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_alloc (obstack, length); +} + +POINTER (obstack_copy) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy (obstack, pointer, length); +} + +POINTER (obstack_copy0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy0 (obstack, pointer, length); +} + +#endif /* __STDC__ */ + +#endif /* 0 */ + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/lib/obstack.h b/lib/obstack.h new file mode 100644 index 00000000..2f5ec61a --- /dev/null +++ b/lib/obstack.h @@ -0,0 +1,516 @@ +/* obstack.h - object stack macros + Copyright (C) 1988, 89, 90, 91, 92, 93, 94 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, 675 Mass Ave, Cambridge, MA 02139, 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__ + +/* We use subtraction of (char *)0 instead of casting to int + because on word-addressable machines a simple cast to int + may ignore the byte-within-word field of the pointer. */ + +#ifndef __PTR_TO_INT +#define __PTR_TO_INT(P) ((P) - (char *)0) +#endif + +#ifndef __INT_TO_PTR +#define __INT_TO_PTR(P) ((P) + (char *)0) +#endif + +/* We need the type of the resulting object. In ANSI C it is ptrdiff_t + but in traditional C it is usually long. If we are in ANSI C and + don't already have ptrdiff_t get it. */ + +#if defined (__STDC__) && __STDC__ && ! defined (offsetof) +#if defined (__GNUC__) && defined (IN_GCC) +/* On Next machine, the system's stddef.h screws up if included + after we have defined just ptrdiff_t, so include all of stddef.h. + Otherwise, define just ptrdiff_t, which is all we need. */ +#ifndef __NeXT__ +#define __need_ptrdiff_t +#endif +#endif + +#include <stddef.h> +#endif + +#if defined (__STDC__) && __STDC__ +#define PTR_INT_TYPE ptrdiff_t +#else +#define PTR_INT_TYPE long +#endif + +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 */ + PTR_INT_TYPE temp; /* Temporary for some macros. */ + int alignment_mask; /* Mask of alignment for each object. */ + struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ + void (*freefun) (); /* User's function to free a chunk. */ + char *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; /* chunk alloc func returned 0 */ +}; + +/* Declare the external functions we use; they are in obstack.c. */ + +#if defined (__STDC__) && __STDC__ +extern void _obstack_newchunk (struct obstack *, int); +extern void _obstack_free (struct obstack *, void *); +extern int _obstack_begin (struct obstack *, int, int, + void *(*) (), void (*) ()); +extern int _obstack_begin_1 (struct obstack *, int, int, + void *(*) (), void (*) (), void *); +#else +extern void _obstack_newchunk (); +extern void _obstack_free (); +extern int _obstack_begin (); +extern int _obstack_begin_1 (); +#endif + +#if defined (__STDC__) && __STDC__ + +/* Do the function-declarations after the structs + but before defining the macros. */ + +void obstack_init (struct obstack *obstack); + +void * obstack_alloc (struct obstack *obstack, int size); + +void * obstack_copy (struct obstack *obstack, void *address, int size); +void * obstack_copy0 (struct obstack *obstack, void *address, int size); + +void obstack_free (struct obstack *obstack, void *block); + +void obstack_blank (struct obstack *obstack, int size); + +void obstack_grow (struct obstack *obstack, void *data, int size); +void obstack_grow0 (struct obstack *obstack, void *data, int size); + +void obstack_1grow (struct obstack *obstack, int data_char); +void obstack_ptr_grow (struct obstack *obstack, void *data); +void obstack_int_grow (struct obstack *obstack, int data); + +void * obstack_finish (struct obstack *obstack); + +int obstack_object_size (struct obstack *obstack); + +int obstack_room (struct obstack *obstack); +void obstack_1grow_fast (struct obstack *obstack, int data_char); +void obstack_ptr_grow_fast (struct obstack *obstack, void *data); +void obstack_int_grow_fast (struct obstack *obstack, int data); +void obstack_blank_fast (struct obstack *obstack, int size); + +void * obstack_base (struct obstack *obstack); +void * obstack_next_free (struct obstack *obstack); +int obstack_alignment_mask (struct obstack *obstack); +int obstack_chunk_size (struct obstack *obstack); + +#endif /* __STDC__ */ + +/* Non-ANSI C cannot really support alternative functions for these macros, + so we do not declare them. */ + +/* 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) ((h)->alloc_failed ? 0 : (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)->alloc_failed ? 0 : (h)->next_free) + +/* Mask specifying low bits that should be clear in address of an object. */ + +#define obstack_alignment_mask(h) ((h)->alignment_mask) + +#define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) + +#define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) + +#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) ()) (chunkfun), (void (*) ()) (freefun)) + +#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg)) + +#define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun)) + +#define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)()) (newfreefun)) + +#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) + +#define obstack_blank_fast(h,n) ((h)->next_free += (n)) + +#if defined (__GNUC__) && defined (__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 *__o = (OBSTACK); \ + __o->alloc_failed ? 0 : \ + (unsigned) (__o->next_free - __o->object_base); }) + +#define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + (unsigned) (__o->chunk_limit - __o->next_free); }) + +#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); \ + if (!__o->alloc_failed) \ + { \ + bcopy ((char *) (where), __o->next_free, __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); \ + if (!__o->alloc_failed) \ + { \ + bcopy ((char *) (where), __o->next_free, __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); \ + if (!__o->alloc_failed) \ + *(__o->next_free)++ = (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 *)); \ + if (!__o->alloc_failed) \ + *((void **)__o->next_free)++ = ((void *)datum); \ + (void) 0; }) + +#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)); \ + if (!__o->alloc_failed) \ + *((int *)__o->next_free)++ = ((int)datum); \ + (void) 0; }) + +#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr) +#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) + +#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); \ + if (!__o->alloc_failed) \ + __o->next_free += __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; \ + if (__o1->alloc_failed) \ + value = 0; \ + else \ + { \ + value = (void *) __o1->object_base; \ + if (__o1->next_free == value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ + & ~ (__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 = __obj; \ + else (obstack_free) (__o, __obj); }) + +#else /* not __GNUC__ or not __STDC__ */ + +#define obstack_object_size(h) \ + (unsigned) ((h)->alloc_failed ? 0 : (h)->next_free - (h)->object_base) + +#define obstack_room(h) \ + (unsigned) ((h)->chunk_limit - (h)->next_free) + +/* 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_grow(h,where,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + ((h)->alloc_failed ? 0 : \ + (bcopy ((char *) (where), (h)->next_free, (h)->temp), \ + (h)->next_free += (h)->temp))) + +#define obstack_grow0(h,where,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ + ((h)->alloc_failed ? 0 : \ + (bcopy ((char *) (where), (h)->next_free, (h)->temp), \ + (h)->next_free += (h)->temp, \ + *((h)->next_free)++ = 0))) + +#define obstack_1grow(h,datum) \ +( (((h)->next_free + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + ((h)->alloc_failed ? 0 : \ + (*((h)->next_free)++ = (datum)))) + +#define obstack_ptr_grow(h,datum) \ +( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + ((h)->alloc_failed ? 0 : \ + (*((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum)))) + +#define obstack_int_grow(h,datum) \ +( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + ((h)->alloc_failed ? 0 : \ + (*((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum)))) + +#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr) +#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) + +#define obstack_blank(h,length) \ +( (h)->temp = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + ((h)->alloc_failed ? 0 : \ + ((h)->next_free += (h)->temp))) + +#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)->alloc_failed ? 0 : \ + (((h)->next_free == (h)->object_base \ + ? (((h)->maybe_empty_object = 1), 0) \ + : 0), \ + (h)->temp = __PTR_TO_INT ((h)->object_base), \ + (h)->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ + & ~ ((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, \ + __INT_TO_PTR ((h)->temp))) + +#if defined (__STDC__) && __STDC__ +#define obstack_free(h,obj) \ +( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) +#else +#define obstack_free(h,obj) \ +( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0))) +#endif + +#endif /* not __GNUC__ or not __STDC__ */ + +#endif /* not __OBSTACK_H__ */ diff --git a/lib/regex.c b/lib/regex.c new file mode 100644 index 00000000..33c7ea24 --- /dev/null +++ b/lib/regex.c @@ -0,0 +1,5244 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P10003.2/D11.2, except for + internationalization features.) + + Copyright (C) 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (REGEX_MALLOC) + #pragma alloca +#endif + +#define _GNU_SOURCE + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +#include <sys/types.h> + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +#ifdef emacs + +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +/* Emacs uses `NULL' as a predicate. */ +#undef NULL + +#else /* not emacs */ + +#ifdef STDC_HEADERS +#include <stdlib.h> +#else +char *malloc (); +char *realloc (); +#endif + + +/* We used to test for `BSTRING' here, but only GCC and Emacs define + `BSTRING', as far as I know, and neither of them use this code. */ +#ifndef INHIBIT_STRING_HEADER +#if HAVE_STRING_H || STDC_HEADERS +#include <string.h> +#ifndef bcmp +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#endif +#ifndef bcopy +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#endif +#ifndef bzero +#define bzero(s, n) memset ((s), 0, (n)) +#endif +#else +#include <strings.h> +#endif +#endif + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +/* How many characters in the character set. */ +#define CHAR_SET_SIZE 256 + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +#endif /* not SYNTAX_TABLE */ + +#define SYNTAX(c) re_syntax_table[c] + +#endif /* not emacs */ + +/* Get the interface, including the syntax bits. */ +#include "regex.h" + +/* isalpha etc. are used for the character classes. */ +#include <ctype.h> + +/* Jim Meyering writes: + + "... Some ctype macros are valid only for character codes that + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + using /bin/cc or gcc but without giving an ansi option). So, all + ctype uses should be through macros like ISPRINT... If + STDC_HEADERS is defined, then autoconf has verified that the ctype + macros don't need to be guarded with references to isascii. ... + Defining isascii to 1 should let any compiler worth its salt + eliminate the && through constant folding." */ + +#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) +#define ISASCII(c) 1 +#else +#define ISASCII(c) isascii(c) +#endif + +#ifdef isblank +#define ISBLANK(c) (ISASCII (c) && isblank (c)) +#else +#define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif +#ifdef isgraph +#define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +#else +#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +#endif + +#define ISPRINT(c) (ISASCII (c) && isprint (c)) +#define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +#define ISALNUM(c) (ISASCII (c) && isalnum (c)) +#define ISALPHA(c) (ISASCII (c) && isalpha (c)) +#define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +#define ISLOWER(c) (ISASCII (c) && islower (c)) +#define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +#define ISSPACE(c) (ISASCII (c) && isspace (c)) +#define ISUPPER(c) (ISASCII (c) && isupper (c)) +#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +#ifndef NULL +#define NULL 0 +#endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +#ifdef REGEX_MALLOC + +#define REGEX_ALLOCATE malloc +#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) + +#else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +#ifndef alloca + +/* Make alloca work the best possible way. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if HAVE_ALLOCA_H +#include <alloca.h> +#else /* not __GNUC__ or HAVE_ALLOCA_H */ +#ifndef _AIX /* Already did AIX, up at the top. */ +char *alloca (); +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not __GNUC__ */ + +#endif /* not alloca */ + +#define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +#define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + bcopy (source, destination, osize), \ + destination) + +#endif /* not REGEX_MALLOC */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +#define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define RETALLOC_IF(addr, n, t) \ + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) +#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +#define BYTEWIDTH 8 /* In bits. */ + +#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +#undef MAX +#undef MIN +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +#define false 0 +#define true 1 + +static int re_match_2_internal (); + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. */ + +typedef enum +{ + no_op = 0, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn, + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +#ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +#endif /* emacs */ +} re_opcode_t; + +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ + +#define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ + +#define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += 2; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ + +#define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) + +#ifdef DEBUG +static void +extract_number (dest, source) + int *dest; + unsigned char *source; +{ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +} + +#ifndef EXTRACT_MACROS /* To debug the macros. */ +#undef EXTRACT_NUMBER +#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += 2; \ + } while (0) + +#ifdef DEBUG +static void +extract_number_and_incr (destination, source) + int *destination; + unsigned char **source; +{ + extract_number (destination, *source); + *source += 2; +} + +#ifndef EXTRACT_MACROS +#undef EXTRACT_NUMBER_AND_INCR +#define EXTRACT_NUMBER_AND_INCR(dest, src) \ + extract_number_and_incr (&dest, &src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +#ifdef DEBUG + +/* We use standard I/O for debugging. */ +#include <stdio.h> + +/* It is useful to test things that ``must'' be true when debugging. */ +#include <assert.h> + +static int debug = 0; + +#define DEBUG_STATEMENT(e) e +#define DEBUG_PRINT1(x) if (debug) printf (x) +#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) print_partial_compiled_pattern (s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) print_double_string (w, s1, sz1, s2, sz2) + + +extern void printchar (); + +/* Print the fastmap in human-readable form. */ + +void +print_fastmap (fastmap) + char *fastmap; +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + printchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + printchar (i - 1); + } + } + } + putchar ('\n'); +} + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +print_partial_compiled_pattern (start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + printf ("%d:\t", p - start); + + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + printchar (*p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%d", mcnt, *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%d", mcnt, *p++); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c, last = -100; + register int in_range = 0; + + printf ("/charset [%s", + (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); + + assert (p + *p < pend); + + for (c = 0; c < 256; c++) + if (c / 8 < *p + && (p[1 + (c/8)] & (1 << (c % 8)))) + { + /* Are we starting a range? */ + if (last + 1 == c && ! in_range) + { + putchar ('-'); + in_range = 1; + } + /* Have we broken a range? */ + else if (last + 1 != c && in_range) + { + printchar (last); + in_range = 0; + } + + if (! in_range) + printchar (c); + + last = c; + } + + if (in_range) + printchar (last); + + putchar (']'); + + p += 1 + *p; + } + break; + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_jump to %d", p + mcnt - start); + break; + + case on_failure_keep_string_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_keep_string_jump to %d", p + mcnt - start); + break; + + case dummy_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/dummy_failure_jump to %d", p + mcnt - start); + break; + + case push_dummy_failure: + printf ("/push_dummy_failure"); + break; + + case maybe_pop_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/maybe_pop_jump to %d", p + mcnt - start); + break; + + case pop_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/pop_failure_jump to %d", p + mcnt - start); + break; + + case jump_past_alt: + extract_number_and_incr (&mcnt, &p); + printf ("/jump_past_alt to %d", p + mcnt - start); + break; + + case jump: + extract_number_and_incr (&mcnt, &p); + printf ("/jump to %d", p + mcnt - start); + break; + + case succeed_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/succeed_n to %d, %d times", p + mcnt - start, mcnt2); + break; + + case jump_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/jump_n to %d, %d times", p + mcnt - start, mcnt2); + break; + + case set_number_at: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/set_number_at location %d to %d", p + mcnt - start, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + +#ifdef emacs + case before_dot: + printf ("/before_dot"); + break; + + case at_dot: + printf ("/at_dot"); + break; + + case after_dot: + printf ("/after_dot"); + break; + + case syntaxspec: + printf ("/syntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; + + case notsyntaxspec: + printf ("/notsyntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; +#endif /* emacs */ + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + + putchar ('\n'); + } + + printf ("%d:\tend of pattern.\n", p - start); +} + + +void +print_compiled_pattern (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); + printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + + printf ("re_nsub: %d\t", bufp->re_nsub); + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %d\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +print_double_string (where, string1, size1, string2, size2) + const char *where; + const char *string1; + const char *string2; + int size1; + int size2; +{ + unsigned this_char; + + if (where == NULL) + printf ("(null)"); + else + { + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + printchar (string1[this_char]); + + where = string2; + } + + for (this_char = where - string2; this_char < size2; this_char++) + printchar (string2[this_char]); + } +} + +#else /* not DEBUG */ + +#undef assert +#define assert(e) + +#define DEBUG_STATEMENT(e) +#define DEBUG_PRINT1(x) +#define DEBUG_PRINT2(x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +#endif /* not DEBUG */ + +/* 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. */ +reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; + + +/* 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; +} + +/* 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. */ + +static const char *re_error_msg[] = + { NULL, /* REG_NOERROR */ + "No match", /* REG_NOMATCH */ + "Invalid regular expression", /* REG_BADPAT */ + "Invalid collation character", /* REG_ECOLLATE */ + "Invalid character class name", /* REG_ECTYPE */ + "Trailing backslash", /* REG_EESCAPE */ + "Invalid back reference", /* REG_ESUBREG */ + "Unmatched [ or [^", /* REG_EBRACK */ + "Unmatched ( or \\(", /* REG_EPAREN */ + "Unmatched \\{", /* REG_EBRACE */ + "Invalid content of \\{\\}", /* REG_BADBR */ + "Invalid range end", /* REG_ERANGE */ + "Memory exhausted", /* REG_ESPACE */ + "Invalid preceding regular expression", /* REG_BADRPT */ + "Premature end of regular expression", /* REG_EEND */ + "Regular expression too big", /* REG_ESIZE */ + "Unmatched ) or \\)", /* REG_ERPAREN */ + }; + +/* Avoiding alloca during matching, to placate r_alloc. */ + +/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the + searching and matching functions should not call alloca. On some + systems, alloca is implemented in terms of malloc, and if we're + using the relocating allocator routines, then malloc could cause a + relocation, which might (if the strings being searched are in the + ralloc heap) shift the data out from underneath the regexp + routines. + + Here's another reason to avoid allocation: Emacs + processes input from X in a signal handler; processing X input may + call malloc; if input arrives while a matching routine is calling + malloc, then we're scrod. But Emacs can't just block input while + calling matching routines; then we don't notice interrupts when + they come in. So, Emacs blocks input around all regexp calls + except the matching calls, which it leaves unprotected, in the + faith that they will not malloc. */ + +/* Normally, this is fine. */ +#define MATCH_MAY_ALLOCATE + +/* The match routines may not allocate if (1) they would do it with malloc + and (2) it's not safe for them to use malloc. */ +#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && (defined (emacs) || defined (REL_ALLOC)) +#undef MATCH_MAY_ALLOCATE +#endif + + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +#define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_SPACE each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ +int re_max_failures = 2000; + +typedef unsigned char *fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) + + +/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ + +#ifdef MATCH_MAY_ALLOCATE +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) +#else +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.avail = 0; \ + } while (0) +#endif + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push PATTERN_OP on FAIL_STACK. + + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (fail_stack)) \ + ? 0 \ + : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ + 1)) + +/* This pushes an item onto the failure stack. Must be a four-byte + value. Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ITEM(item) \ + fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item + +/* The complement operation. Assumes `fail_stack' is nonempty. */ +#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +#define DEBUG_PUSH PUSH_FAILURE_ITEM +#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () +#else +#define DEBUG_PUSH(item) +#define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be + declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + int this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + PUSH_FAILURE_ITEM (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + PUSH_FAILURE_ITEM (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ + PUSH_FAILURE_ITEM (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ + PUSH_FAILURE_ITEM (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_ITEM (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_ITEM (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +#define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ + int this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_ITEM (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ + \ + low_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ + \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + } \ + \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + + + +/* Structure for per-register (a.k.a. per-group) information. + This must not be longer than one word, because we push this value + onto the failure stack. Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + unsigned r; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + while (0) + + +/* Registers are set to a sentinel when they haven't yet matched. */ +#define REG_UNSET_VALUE ((char *) -1) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + + + +/* How do we implement a missing MATCH_MAY_ALLOCATE? + We make the fail stack a global thing, and then grow it to + re_max_failures when we compile. */ +#ifndef MATCH_MAY_ALLOCATE +static fail_stack_type fail_stack; + +static const char ** regstart, ** regend; +static const char ** old_regstart, ** old_regend; +static const char **best_regstart, **best_regend; +static register_info_type *reg_info; +static const char **reg_dummy; +static register_info_type *reg_info_dummy; +#endif + + +/* Subroutine declarations and macros for regex_compile. */ + +static void store_op1 (), store_op2 (); +static void insert_op1 (), insert_op2 (); +static boolean at_begline_loc_p (), at_endline_loc_p (); +static boolean group_in_compile_stack (); +static reg_errcode_t compile_range (); + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +#define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = translate[c]; \ + } while (0) + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +#define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 32 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + while (b - bufp->buffer + (n) > bufp->allocated) \ + EXTEND_BUFFER () + +/* Make sure we have one more byte of buffer space and then add C to it. */ +#define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (unsigned char) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +#define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +#define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + *b++ = (unsigned char) (c3); \ + } while (0) + + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +#define STORE_JUMP(op, loc, to) \ + store_op1 (op, loc, (to) - (loc) - 3) + +/* Likewise, for a two-argument jump. */ +#define STORE_JUMP2(op, loc, to, arg) \ + store_op2 (op, loc, (to) - (loc) - 3, arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP(op, loc, to) \ + insert_op1 (op, loc, (to) - (loc) - 3, b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP2(op, loc, to, arg) \ + insert_op2 (op, loc, (to) - (loc) - 3, arg, b) + + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1L << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER() \ + do { \ + unsigned char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + + +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +#define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +typedef int pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +#define INIT_COMPILE_STACK_SIZE 32 + +#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + + +/* Set the bit for character C in a list. */ +#define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) + + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +#define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +/* Return, freeing storage we allocated. */ +#define FREE_STACK_RETURN(value) \ + return (free (compile_stack.stack), value) + +static reg_errcode_t +regex_compile (pattern, size, syntax, bufp) + const char *pattern; + int size; + reg_syntax_t syntax; + struct re_pattern_buffer *bufp; +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register unsigned char c, c1; + + /* A random temporary spot in PATTERN. */ + const char *p1; + + /* Points to the end of the buffer, where we should append. */ + register unsigned char *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ + const char *p = pattern; + const char *pend = pattern + size; + + /* How to translate the characters in the pattern. */ + char *translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + unsigned char *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + unsigned char *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + unsigned char *begalt; + + /* Place in the uncompiled pattern (i.e., the {) to + which to go back if the interval is invalid. */ + const char *beg_interval; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + unsigned char *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + printchar (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + return REG_ESPACE; + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined (emacs) && !defined (SYNTAX_TABLE) + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* 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. */ + RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); + } + if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE); + + bufp->allocated = INIT_BUF_SIZE; + } + + begalt = b = bufp->buffer; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || at_begline_loc_p (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || at_endline_loc_p (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + FREE_STACK_RETURN (REG_BADRPT); + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (3); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - 3); + + /* We've added more stuff to the buffer. */ + b += 3; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 3); + pending_exact = 0; + b += 3; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); + b += 3; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + SET_LIST_BIT (c1); + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + FREE_STACK_RETURN (REG_ERANGE); + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and:`]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + /* This was split into 3 if's to + avoid an arbitrary limit in some compiler. */ + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch))) + SET_LIST_BIT (ch); + if ( (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch))) + SET_LIST_BIT (ch); + if ( (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + FREE_STACK_RETURN (REG_ERPAREN); + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + FREE_STACK_RETURN (REG_ERPAREN); + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + unsigned char *inner_group_loc + = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (on_failure_jump, begalt, b + 6); + pending_exact = 0; + b += 3; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (3); + b += 3; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + || (p - 2 == pattern && p == pend)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + beg_interval = p - 1; + + if (p == pend) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + FREE_STACK_RETURN (REG_EBRACE); + } + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + FREE_STACK_RETURN (REG_BADBR); + } + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\') FREE_STACK_RETURN (REG_EBRACE); + + PATFETCH (c); + } + + if (c != '}') + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + FREE_STACK_RETURN (REG_BADBR); + } + + /* We just parsed a valid interval. */ + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + FREE_STACK_RETURN (REG_BADRPT); + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + INSERT_JUMP (jump, laststart, b + 3); + b += 3; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at <jump count> <upper bound> + set_number_at <succeed_n count> <lower bound> + succeed_n <after jump addr> <succeed_n count> + <body of loop> + jump_n <succeed_n addr> <jump count> + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 10 + (upper_bound > 1) * 10; + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 5 + (upper_bound > 1) * 5, + lower_bound); + b += 5; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + insert_op2 (set_number_at, laststart, 5, lower_bound, b); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op2 (set_number_at, laststart, b - laststart, + upper_bound - 1, b); + b += 5; + } + } + pending_exact = 0; + beg_interval = NULL; + } + break; + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + assert (beg_interval); + p = beg_interval; + beg_interval = NULL; + + /* normal_char and normal_backslash need `c'. */ + PATFETCH (c); + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (p > pattern && p[-1] == '\\') + goto normal_backslash; + } + goto normal_char; + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + BUF_PUSH (wordbeg); + break; + + case '>': + BUF_PUSH (wordend); + break; + + case 'b': + BUF_PUSH (wordbound); + break; + + case 'B': + BUF_PUSH (notwordbound); + break; + + case '`': + BUF_PUSH (begbuf); + break; + + case '\'': + BUF_PUSH (endbuf); + 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) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + FREE_STACK_RETURN (REG_ESUBREG); + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + + BUF_PUSH_2 (exactn, 0); + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + FREE_STACK_RETURN (REG_EPAREN); + + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ + bufp->used = b - bufp->buffer; + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: \n"); + print_compiled_pattern (bufp); + } +#endif /* DEBUG */ + +#ifndef MATCH_MAY_ALLOCATE + /* Initialize the failure stack to the largest possible stack. This + isn't necessary unless we're trying to avoid calling alloca in + the search and match routines. */ + { + int num_regs = bufp->re_nsub + 1; + + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size + is strictly greater than re_max_failures, the largest possible stack + is 2 * re_max_failures failure points. */ + if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) + { + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); + +#ifdef emacs + if (! fail_stack.stack) + fail_stack.stack + = (fail_stack_elt_t *) xmalloc (fail_stack.size + * sizeof (fail_stack_elt_t)); + else + fail_stack.stack + = (fail_stack_elt_t *) xrealloc (fail_stack.stack, + (fail_stack.size + * sizeof (fail_stack_elt_t))); +#else /* not emacs */ + if (! fail_stack.stack) + fail_stack.stack + = (fail_stack_elt_t *) malloc (fail_stack.size + * sizeof (fail_stack_elt_t)); + else + fail_stack.stack + = (fail_stack_elt_t *) realloc (fail_stack.stack, + (fail_stack.size + * sizeof (fail_stack_elt_t))); +#endif /* not emacs */ + } + + /* Initialize some other variables the matcher uses. */ + RETALLOC_IF (regstart, num_regs, const char *); + RETALLOC_IF (regend, num_regs, const char *); + RETALLOC_IF (old_regstart, num_regs, const char *); + RETALLOC_IF (old_regend, num_regs, const char *); + RETALLOC_IF (best_regstart, num_regs, const char *); + RETALLOC_IF (best_regend, num_regs, const char *); + RETALLOC_IF (reg_info, num_regs, register_info_type); + RETALLOC_IF (reg_dummy, num_regs, const char *); + RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); + } +#endif + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ + +static void +store_op1 (op, loc, arg) + re_opcode_t op; + unsigned char *loc; + int arg; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +store_op2 (op, loc, arg1, arg2) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 3, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ + +static void +insert_op1 (op, loc, arg, end) + re_opcode_t op; + unsigned char *loc; + int arg; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 3; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op1 (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +insert_op2 (op, loc, arg1, arg2, end) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 5; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op2 (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +at_begline_loc_p (pattern, p, syntax) + const char *pattern, *p; + reg_syntax_t syntax; +{ + const char *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +at_endline_loc_p (p, pend, syntax) + const char *p, *pend; + int syntax; +{ + const char *next = p; + boolean next_backslash = *next == '\\'; + const char *next_next = p + 1 < pend ? p + 1 : NULL; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack (compile_stack, regnum) + compile_stack_type compile_stack; + regnum_t regnum; +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} + + +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +compile_range (p_ptr, pend, translate, syntax, b) + const char **p_ptr, *pend; + char *translate; + reg_syntax_t syntax; + unsigned char *b; +{ + unsigned this_char; + + const char *p = *p_ptr; + int range_start, range_end; + + if (p == pend) + return REG_ERANGE; + + /* Even though the pattern is a signed `char *', we need to fetch + with unsigned char *'s; if the high bit of the pattern character + is set, the range endpoints will be negative if we fetch using a + signed char *. + + We also want to fetch the endpoints without translating them; the + appropriate translation is done in the bit-setting loop below. */ + /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */ + range_start = ((const unsigned char *) p)[-2]; + range_end = ((const unsigned char *) p)[0]; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* If the start is after the end, the range is empty. */ + if (range_start > range_end) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- the range is inclusive, so if `range_end' == 0xff + (assuming 8-bit characters), we would otherwise go into an infinite + loop, since all characters <= 0xff. */ + for (this_char = range_start; this_char <= range_end; this_char++) + { + SET_LIST_BIT (TRANSLATE (this_char)); + } + + return REG_NOERROR; +} + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +int +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + int j, k; +#ifdef MATCH_MAY_ALLOCATE + fail_stack_type fail_stack; +#endif +#ifndef REGEX_MALLOC + char *destination; +#endif + /* We don't push any register information onto the failure stack. */ + unsigned num_regs = 0; + + register char *fastmap = bufp->fastmap; + unsigned char *pattern = bufp->buffer; + unsigned long size = bufp->used; + unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (p != pend || !FAIL_STACK_EMPTY ()) + { + if (p == pend) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail]; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + return 0; + + + /* Following are the cases which match a character. These end + with `break'. */ + + case exactn: + fastmap[p[1]] = 1; + break; + + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + + + case anychar: + { + int fastmap_newline = fastmap['\n']; + + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = fastmap_newline; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + return 0; + + /* Otherwise, have to check alternative paths. */ + break; + } + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* not emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1] == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + return -2; + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += 2; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 4; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + return 0; +} /* re_compile_fastmap */ + +/* 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; + unsigned 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 = (regoff_t *) 0; + } +} + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search (bufp, string, size, startpos, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, startpos, range; + struct re_registers *regs; +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int startpos; + int range; + struct re_registers *regs; + int stop; +{ + int val; + register char *fastmap = bufp->fastmap; + register char *translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register char c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + return -1; + + val = re_match_2_internal (bufp, string1, size1, string2, size2, + startpos, regs, stop); +#ifndef REGEX_MALLOC +#ifdef C_ALLOCA + alloca (0); +#endif +#endif + + if (val >= 0) + return startpos; + + if (val == -2) + return -2; + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} /* re_search_2 */ + +/* Declarations and macros for re_match_2. */ + +static int bcmp_translate (); +static boolean alt_match_null_string_p (), + common_op_match_null_string_p (), + group_match_null_string_p (); + +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) + +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) + + +/* Free everything we malloc. */ +#ifdef MATCH_MAY_ALLOCATE +#ifdef REGEX_MALLOC +#define FREE_VAR(var) if (var) free (var); var = NULL +#define FREE_VARIABLES() \ + do { \ + FREE_VAR (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +#else /* not REGEX_MALLOC */ +/* This used to do alloca (0), but now we do that in the caller. */ +#define FREE_VARIABLES() /* Nothing */ +#endif /* not REGEX_MALLOC */ +#else +#define FREE_VARIABLES() /* Do nothing! */ +#endif /* not MATCH_MAY_ALLOCATE */ + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match (bufp, string, size, pos, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, pos; + struct re_registers *regs; +{ + int result = re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size); + alloca (0); + return result; +} +#endif /* not emacs */ + + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + int result = re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop); + alloca (0); + return result; +} + +/* This is a separate function so that we can force an alloca cleanup + afterwards. */ +static int +re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + /* General temporaries. */ + int mcnt; + unsigned char *p1; + + /* Just past the end of the corresponding string. */ + const char *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const char *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const char *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ + unsigned char *p = bufp->buffer; + register unsigned char *pend = p + bufp->used; + + /* Mark the opcode just after a start_memory, so we can test for an + empty subpattern when we get to the stop_memory. */ + unsigned char *just_past_start_mem = 0; + + /* We use this to map every character in the string. */ + char *translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + fail_stack_type fail_stack; +#endif +#ifdef DEBUG + static unsigned failure_id = 0; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + unsigned num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; + unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **regstart, **regend; +#endif + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **old_regstart, **old_regend; +#endif + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + register_info_type *reg_info; +#endif + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **best_regstart, **best_regend; +#endif + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const char *match_end = NULL; + + /* Used when we pop values we don't care about. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **reg_dummy; + register_info_type *reg_info_dummy; +#endif + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + +#ifdef MATCH_MAY_ALLOCATE + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const char *); + regend = REGEX_TALLOC (num_regs, const char *); + old_regstart = REGEX_TALLOC (num_regs, const char *); + old_regend = REGEX_TALLOC (num_regs, const char *); + best_regstart = REGEX_TALLOC (num_regs, const char *); + best_regend = REGEX_TALLOC (num_regs, const char *); + reg_info = REGEX_TALLOC (num_regs, register_info_type); + reg_dummy = REGEX_TALLOC (num_regs, const char *); + reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } +#if defined (REGEX_MALLOC) + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (register_info_type *) NULL; + } +#endif /* REGEX_MALLOC */ +#endif /* MATCH_MAY_ALLOCATE */ + + /* The starting position is bogus. */ + if (pos < 0 || pos > size1 + size2) + { + FREE_VARIABLES (); + return -1; + } + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } + + DEBUG_PRINT1 ("The compiled pattern is: "); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { + DEBUG_PRINT2 ("\n0x%x: ", p); + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + /* 1 if this match ends in the same string (string1 or string2) + as the best previous match. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + /* 1 if this match is the best seen so far. */ + boolean best_match_p; + + /* AIX compiler got confused when this was combined + with the previous declaration. */ + if (same_str_p) + best_match_p = d > match_end; + else + best_match_p = !MATCHING_IN_FIRST_STRING; + + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + + /* If exceeds best match so far, save it. */ + if (!best_regs_set || best_match_p) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. And if + last match is real best match, don't restore second + best one. */ + else if (best_regs_set && !best_match_p) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + DEBUG_PRINT1 ("Accepting match.\n"); + + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->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 (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + } + } + else + { + /* These braces fend off a "empty body in an else-statement" + warning under GCC when assert expands to nothing. */ + assert (bufp->regs_allocated == REGS_FIXED); + } + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + FREE_VARIABLES (); + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + return mcnt; + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); + if (translate[(unsigned char) *d++] != (char) *p++) + goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (char) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", *d); + d++; + break; + + + case charset: + case charset_not: + { + register unsigned char c; + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ + + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + just_past_start_mem = p; + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + unsigned char r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || just_past_start_mem == p - 1) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += 2; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < *p + *(p + 1); r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if ((int) old_regend[r] >= (int) regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: + { + register const char *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate (d, d2, mcnt, translate) + : bcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. + If what follows this loop is a ...+ construct, + look at what begins its body, since we will have to + match at least one of that. */ + while (1) + { + if (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; + else if (p2 + 6 < pend + && (re_opcode_t) *p2 == dummy_failure_jump) + p2 += 6; + else + break; + } + + p1 = p + mcnt; + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + + if ((re_opcode_t) p1[3] == exactn && p1[5] != c) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned char) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + else if ((re_opcode_t) *p2 == charset) + { +#ifdef DEBUG + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; +#endif + + if ((re_opcode_t) p1[3] == exactn + && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4] + && (p2[1 + p1[4] / BYTEWIDTH] + & (1 << (p1[4] % BYTEWIDTH))))) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset_not) + { + int idx; + /* We win if the charset_not inside the loop + lists every character listed in the charset after. */ + for (idx = 0; idx < (int) p2[1]; idx++) + if (! (p2[2 + idx] == 0 + || (idx < (int) p1[4] + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) + break; + + if (idx == p2[1]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + else if ((re_opcode_t) p1[3] == charset) + { + int idx; + /* We win if the charset inside the loop + has no overlap with the one after the loop. */ + for (idx = 0; + idx < (int) p2[1] && idx < (int) p1[4]; + idx++) + if ((p2[2 + idx] & p1[5 + idx]) != 0) + break; + + if (idx == p2[1] || idx == p1[4]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + } + p -= 2; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (unsigned char) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + unsigned dummy_low_reg, dummy_high_reg; + unsigned char *pdummy; + const char *sdummy; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + + /* Unconditionally jump (without popping any failure points). */ + case jump: + unconditional_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ + DEBUG_PRINT2 ("(to 0x%x).\n", p); + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (0, 0, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (0, 0, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); + } + else if (mcnt == 0) + { + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); + p[2] = (unsigned char) no_op; + p[3] = (unsigned char) no_op; + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + 2, mcnt); + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); + STORE_NUMBER (p1, mcnt); + break; + } + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) + break; + goto fail; + +#ifdef emacs + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; +#if 0 /* not emacs19 */ + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) + goto fail; + break; +#endif /* not emacs19 */ + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +group_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + /* Point to after the args to the start_memory. */ + unsigned char *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); + + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +alt_match_null_string_p (p, end, reg_info) + unsigned char *p, *end; + register_info_type *reg_info; +{ + int mcnt; + unsigned char *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +common_op_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + boolean ret; + int reg_no; + unsigned char *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = group_match_null_string_p (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += 2; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 4; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 4; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +bcmp_translate (s1, s2, len, translate) + unsigned char *s1, *s2; + register int len; + char *translate; +{ + register unsigned char *p1 = s1, *p2 = s2; + while (len) + { + if (translate[*p1++] != translate[*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) 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. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern (pattern, length, bufp) + const char *pattern; + int length; + struct re_pattern_buffer *bufp; +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* 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. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = regex_compile (pattern, length, re_syntax_options, bufp); + + return re_error_msg[(int) ret]; +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#ifdef _REGEX_RE_COMP + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp (s) + const char *s; +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return "Memory exhausted"; + } + + /* 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 = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + /* Yes, we're discarding `const' here. */ + return (char *) re_error_msg[(int) ret]; +} + + +int +re_exec (s) + const char *s; +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} +#endif /* _REGEX_RE_COMP */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* 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' and `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 *preg; + const char *pattern; + int cflags; +{ + reg_errcode_t ret; + unsigned syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + preg->used = 0; + + /* Don't bother to use a fastmap when searching. This simplifies the + REG_NEWLINE case: if we used a fastmap, we'd have to put all the + characters after newlines into the fastmap. This way, we just try + every character. */ + preg->fastmap = 0; + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate = (char *) malloc (CHAR_SET_SIZE); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? tolower (i) : i; + } + else + preg->translate = NULL; + + /* 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); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ + ret = regex_compile (pattern, strlen (pattern), syntax, preg); + + /* 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; + + return (int) ret; +} + + +/* 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 *preg; + const char *string; + size_t nmatch; + regmatch_t pmatch[]; + int eflags; +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch, regoff_t); + regs.end = TALLOC (nmatch, regoff_t); + if (regs.start == NULL || regs.end == NULL) + return (int) REG_NOMATCH; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + free (regs.end); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} + + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (errcode, preg, errbuf, errbuf_size) + int errcode; + const regex_t *preg; + char *errbuf; + size_t errbuf_size; +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[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 = re_error_msg[errcode]; + + /* POSIX doesn't require that we do anything in this case, but why + not be nice. */ + if (! msg) + msg = "Success"; + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { + strncpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + strcpy (errbuf, msg); + } + + return msg_size; +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (preg) + regex_t *preg; +{ + if (preg->buffer != NULL) + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + if (preg->fastmap != NULL) + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + if (preg->translate != NULL) + free (preg->translate); + preg->translate = NULL; +} + +#endif /* not emacs */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/lib/regex.h b/lib/regex.h new file mode 100644 index 00000000..55927f62 --- /dev/null +++ b/lib/regex.h @@ -0,0 +1,487 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + + Copyright (C) 1985, 89, 90, 91, 92, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __REGEXP_LIBRARY_H__ +#define __REGEXP_LIBRARY_H__ + +/* POSIX says that <sys/types.h> must be included (by the caller) before + <regex.h>. */ + +#ifdef VMS +/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it + should be there. */ +#include <stddef.h> +#endif + + +/* 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 reg_syntax_t; + +/* 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 (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 \<digit> matches <digit>. + If not set, then \<digit> 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) + +/* 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; + +/* 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_UNMATCHED_RIGHT_PAREN_ORD) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) + +#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) + +/* 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) + +/* 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_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS 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]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +#undef RE_DUP_MAX +#endif +#define RE_DUP_MAX ((1 << 15) - 1) + + +/* 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 (REG_EXTENDED << 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 (REG_ICASE << 1) + +/* 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 (REG_NEWLINE << 1) + + +/* 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) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ + 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, /* Not implemented. */ + 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; + +/* 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 +{ +/* [[[begin 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 *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t 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 *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. */ + char *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 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. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned 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 fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the + beginning of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_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 +{ + unsigned num_regs; + regoff_t *start; + regoff_t *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. */ +#ifndef RE_NREGS +#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. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +#define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +#define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* 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 _RE_ARGS ((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 + _RE_ARGS ((const char *pattern, int 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 _RE_ARGS ((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 int re_search + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, int 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 int re_search_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop)); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs)); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int 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 + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +#ifdef _REGEX_RE_COMP +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); +#endif + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); +extern int regexec + _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags)); +extern size_t regerror + _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size)); +extern void regfree _RE_ARGS ((regex_t *preg)); + +#endif /* not __REGEXP_LIBRARY_H__ */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/lib/strtol.c b/lib/strtol.c new file mode 100644 index 00000000..08ef0a47 --- /dev/null +++ b/lib/strtol.c @@ -0,0 +1,186 @@ +/* Copyright (C) 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <ctype.h> +#include <errno.h> + +#if HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX ((unsigned long) ~(unsigned long) 0) +#endif + +#ifndef LONG_MAX +#define LONG_MAX (~(1 << (sizeof (long) * 8 - 1))) +#endif + +#ifndef LONG_MIN +#define LONG_MIN (-LONG_MAX - 1) +#endif + +#if STDC_HEADERS +#include <stddef.h> +#include <stdlib.h> +#else +#define NULL 0 +extern int errno; +#endif + +#ifndef UNSIGNED +#define UNSIGNED 0 +#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. */ +#if UNSIGNED +unsigned long int +#define strtol strtoul +#else +long int +#endif +strtol (nptr, endptr, base) + const char *nptr; + char **endptr; + int base; +{ + int negative; + register unsigned long int cutoff; + register unsigned int cutlim; + register unsigned long int i; + register const char *s; + register unsigned char c; + const char *save; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + + /* Skip white space. */ + while (isspace (*s)) + ++s; + if (*s == '\0') + goto noconv; + + /* Check for a sign. */ + if (*s == '-') + { + negative = 1; + ++s; + } + else if (*s == '+') + { + negative = 0; + ++s; + } + else + negative = 0; + + if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X') + s += 2; + + /* If BASE is zero, figure it out ourselves. */ + if (base == 0) + { + if (*s == '0') + { + if (toupper (s[1]) == 'X') + { + s += 2; + base = 16; + } + else + base = 8; + } + else + base = 10; + } + + /* Save the pointer so we can check later if anything happened. */ + save = s; + + cutoff = ULONG_MAX / (unsigned long int) base; + cutlim = ULONG_MAX % (unsigned long int) base; + + overflow = 0; + i = 0; + for (c = *s; c != '\0'; c = *++s) + { + if (isdigit (c)) + c -= '0'; + else if (isalpha (c)) + c = toupper (c) - 'A' + 10; + else + break; + if (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 = (char *) s; + +#if !UNSIGNED + /* Check for a value that is within the range of + `unsigned long int', but outside the range of `long int'. */ + if (i > (negative ? + -(unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX)) + overflow = 1; +#endif + + if (overflow) + { + errno = ERANGE; +#if UNSIGNED + return ULONG_MAX; +#else + return negative ? LONG_MIN : LONG_MAX; +#endif + } + + /* Return the result of the appropriate sign. */ + return (negative ? -i : i); + +noconv:; + /* There was no number to convert. */ + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; +} diff --git a/lib/xmalloc.c b/lib/xmalloc.c new file mode 100644 index 00000000..9f701111 --- /dev/null +++ b/lib/xmalloc.c @@ -0,0 +1,95 @@ +/* xmalloc.c -- malloc with out of memory checking + Copyright (C) 1990, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if __STDC__ +#define VOID void +#else +#define VOID char +#endif + +#include <sys/types.h> + +#if STDC_HEADERS +#include <stdlib.h> +#else +VOID *malloc (); +VOID *realloc (); +void free (); +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +/* Exit value when the requested amount of memory is not available. + The caller may set it to some other value. */ +int xmalloc_exit_failure = EXIT_FAILURE; + +#if __STDC__ && (HAVE_VPRINTF || HAVE_DOPRNT) +void error (int, int, const char *, ...); +#else +void error (); +#endif + +static VOID * +fixup_null_alloc (n) + size_t n; +{ + VOID *p; + + p = 0; + if (n == 0) + p = malloc ((size_t) 1); + if (p == 0) + error (xmalloc_exit_failure, 0, "memory exhausted"); + return p; +} + +/* Allocate N bytes of memory dynamically, with error checking. */ + +VOID * +xmalloc (n) + size_t n; +{ + VOID *p; + + p = malloc (n); + if (p == 0) + p = fixup_null_alloc (n); + return p; +} + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. + If P is NULL, run xmalloc. */ + +VOID * +xrealloc (p, n) + VOID *p; + size_t n; +{ + if (p == 0) + return xmalloc (n); + p = realloc (p, n); + if (p == 0) + p = fixup_null_alloc (n); + return p; +} diff --git a/lib/xstrdup.c b/lib/xstrdup.c new file mode 100644 index 00000000..27cd0c67 --- /dev/null +++ b/lib/xstrdup.c @@ -0,0 +1,36 @@ +/* xstrdup.c -- copy a string with out of memory checking + Copyright (C) 1990 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if defined(STDC_HEADERS) || defined(HAVE_STRING_H) +#include <string.h> +#else +#include <strings.h> +#endif +char *xmalloc (); + +/* Return a newly allocated copy of STRING. */ + +char * +xstrdup (string) + char *string; +{ + return strcpy (xmalloc (strlen (string) + 1), string); +} diff --git a/libltdl/COPYING.LIB b/libltdl/COPYING.LIB new file mode 100644 index 00000000..eb685a5e --- /dev/null +++ b/libltdl/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am new file mode 100644 index 00000000..12bdcbbf --- /dev/null +++ b/libltdl/Makefile.am @@ -0,0 +1,44 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = no-dependencies foreign + +if INSTALL_LTDL +include_HEADERS = ltdl.h +lib_LTLIBRARIES = libltdl.la +else +noinst_HEADERS = ltdl.h +endif + +if CONVENIENCE_LTDL +noinst_LTLIBRARIES = libltdlc.la +endif + +libltdl_la_SOURCES = ltdl.c +libltdl_la_LDFLAGS = -version-info 1:1:1 +libltdl_la_LIBADD = $(LIBADD_DL) + +libltdlc_la_SOURCES = ltdl.c +libltdlc_la_LIBADD = $(LIBADD_DL) + +## Because we do not have automatic dependency tracking: +ltdl.lo: ltdl.h config.h + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +## This allows us to install libltdl without using ln and without creating +## a world writeable directory. +## FIXME: Removed this rule once automake can do this properly by itself. +local-install-files: $(DISTFILES) + -rm -rf $(DESTDIR)$(datadir)/libtool/libltdl + $(mkinstalldirs) $(DESTDIR)$(datadir)/libtool/libltdl + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(DESTDIR)$(datadir)/libtool/libltdl/$$file; \ + else \ + test -f $(DESTDIR)$(datadir)/libtool/libltdl/$$file \ + || cp -p $$d/$$file $(DESTDIR)$(datadir)/libtool/libltdl/$$file || :; \ + fi; \ + done diff --git a/libltdl/Makefile.in b/libltdl/Makefile.in new file mode 100644 index 00000000..6d4c93b2 --- /dev/null +++ b/libltdl/Makefile.in @@ -0,0 +1,454 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 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. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AS = @AS@ +CC = @CC@ +DLLTOOL = @DLLTOOL@ +LD = @LD@ +LIBADD_DL = @LIBADD_DL@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NM = @NM@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ + +AUTOMAKE_OPTIONS = no-dependencies foreign + +@INSTALL_LTDL_TRUE@include_HEADERS = ltdl.h +@INSTALL_LTDL_TRUE@lib_LTLIBRARIES = libltdl.la +@INSTALL_LTDL_FALSE@noinst_HEADERS = ltdl.h + +@CONVENIENCE_LTDL_TRUE@noinst_LTLIBRARIES = libltdlc.la + +libltdl_la_SOURCES = ltdl.c +libltdl_la_LDFLAGS = -version-info 1:1:1 +libltdl_la_LIBADD = $(LIBADD_DL) + +libltdlc_la_SOURCES = ltdl.c +libltdlc_la_LIBADD = $(LIBADD_DL) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libltdl_la_DEPENDENCIES = +libltdl_la_OBJECTS = ltdl.lo +libltdlc_la_LDFLAGS = +libltdlc_la_DEPENDENCIES = +libltdlc_la_OBJECTS = ltdl.lo +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +HEADERS = $(include_HEADERS) $(noinst_HEADERS) + +DIST_COMMON = README ./stamp-h.in COPYING.LIB Makefile.am Makefile.in \ +acconfig.h acinclude.m4 aclocal.m4 config.h.in configure configure.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES) +OBJECTS = $(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +mostlyclean-libLTLIBRARIES: + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + +distclean-libLTLIBRARIES: + +maintainer-clean-libLTLIBRARIES: + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +mostlyclean-noinstLTLIBRARIES: + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + +distclean-noinstLTLIBRARIES: + +maintainer-clean-noinstLTLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libltdl.la: $(libltdl_la_OBJECTS) $(libltdl_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libltdl_la_LDFLAGS) $(libltdl_la_OBJECTS) $(libltdl_la_LIBADD) $(LIBS) + +libltdlc.la: $(libltdlc_la_OBJECTS) $(libltdlc_la_DEPENDENCIES) + $(LINK) $(libltdlc_la_LDFLAGS) $(libltdlc_la_OBJECTS) $(libltdlc_la_LIBADD) $(LIBS) + +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(includedir) + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + list='$(include_HEADERS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(includedir)/$$p; \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-libLTLIBRARIES +install-exec: install-exec-am + +install-data-am: install-includeHEADERS +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-libLTLIBRARIES uninstall-includeHEADERS +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-libLTLIBRARIES \ + mostlyclean-noinstLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-hdr clean-libLTLIBRARIES clean-noinstLTLIBRARIES \ + clean-compile clean-libtool clean-tags clean-generic \ + mostlyclean-am + +clean: clean-am + +distclean-am: distclean-hdr distclean-libLTLIBRARIES \ + distclean-noinstLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-generic \ + clean-am + -rm -f libtool + +distclean: distclean-am + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr \ + maintainer-clean-libLTLIBRARIES \ + maintainer-clean-noinstLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \ +clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \ +uninstall-libLTLIBRARIES install-libLTLIBRARIES \ +mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \ +clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile mostlyclean-libtool distclean-libtool \ +clean-libtool maintainer-clean-libtool uninstall-includeHEADERS \ +install-includeHEADERS tags mostlyclean-tags distclean-tags clean-tags \ +maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck all-recursive-am install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +ltdl.lo: ltdl.h config.h + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +local-install-files: $(DISTFILES) + -rm -rf $(DESTDIR)$(datadir)/libtool/libltdl + $(mkinstalldirs) $(DESTDIR)$(datadir)/libtool/libltdl + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(DESTDIR)$(datadir)/libtool/libltdl/$$file; \ + else \ + test -f $(DESTDIR)$(datadir)/libtool/libltdl/$$file \ + || cp -p $$d/$$file $(DESTDIR)$(datadir)/libtool/libltdl/$$file || :; \ + 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/libltdl/README b/libltdl/README new file mode 100644 index 00000000..0b08ae28 --- /dev/null +++ b/libltdl/README @@ -0,0 +1 @@ +This is GNU libltdl, a system independent dlopen wrapper for GNU libtool. diff --git a/libltdl/acconfig.h b/libltdl/acconfig.h new file mode 100644 index 00000000..15f115c7 --- /dev/null +++ b/libltdl/acconfig.h @@ -0,0 +1,12 @@ +/* Some of these are defined here, not in configure.in, because + they're AC_DEFINEd in two different places, which causes two + defines to appear. Some C compilers might now appreciate it... */ + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD diff --git a/libltdl/acinclude.m4 b/libltdl/acinclude.m4 new file mode 100644 index 00000000..2ad32064 --- /dev/null +++ b/libltdl/acinclude.m4 @@ -0,0 +1,427 @@ +## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*- +## Copyright (C) 1996-1999 Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +## +## 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# serial 40 AC_PROG_LIBTOOL +AC_DEFUN(AC_PROG_LIBTOOL, +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl + +# Save cache, so that ltconfig can load it +AC_CACHE_SAVE + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ +LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ +DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| AC_MSG_ERROR([libtool configure failed]) + +# Reload cache, that may have been modified by ltconfig +AC_CACHE_LOAD + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log +]) + +AC_DEFUN(AC_LIBTOOL_SETUP, +[AC_PREREQ(2.13)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +dnl + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" +ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], +[libtool_flags="$libtool_flags --enable-dlopen"]) +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[libtool_flags="$libtool_flags --enable-win32-dll"]) +AC_ARG_ENABLE(libtool-lock, + [ --disable-libtool-lock avoid locking (might break parallel builds)]) +test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock" +test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +]) +esac +]) + +# AC_LIBTOOL_DLOPEN - enable checks for dlopen support +AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) + +# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's +AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) + +# AC_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AC_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_SHARED, [dnl +define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl +]) + +# AC_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no)]) + +# AC_ENABLE_STATIC - implement the --enable-static flag +# Usage: AC_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_STATIC, [dnl +define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AC_ENABLE_STATIC_DEFAULT)dnl +]) + +# AC_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no)]) + + +# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag +# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl +define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(fast-install, +changequote(<<, >>)dnl +<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl +]) + +# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install +AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no)]) + +# AC_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN(AC_PROG_LD, +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. +changequote(,)dnl + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' +changequote([,])dnl + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_SUBST(LD) +AC_PROG_LD_GNU +]) + +AC_DEFUN(AC_PROG_LD_GNU, +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +]) + +# AC_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN(AC_PROG_NM, +[AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(ac_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi]) +NM="$ac_cv_path_NM" +AC_MSG_RESULT([$NM]) +AC_SUBST(NM) +]) + +# AC_CHECK_LIBM - check for math library +AC_DEFUN(AC_CHECK_LIBM, +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case "$host" in +*-*-beos* | *-*-cygwin*) + # These system don't have libm + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, main, LIBM="-lm") + ;; +esac +]) + +# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl convenience library, adds --enable-ltdl-convenience to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case "$enable_ltdl_convenience" in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la + INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) +]) + +# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl installable library, and adds --enable-ltdl-install to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, main, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la + INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + INCLTDL= + fi +]) + +dnl old names +AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl +AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl +AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl +AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl +AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl +AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl +AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl + +dnl This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL])dnl diff --git a/libltdl/aclocal.m4 b/libltdl/aclocal.m4 new file mode 100644 index 00000000..7ade1e6e --- /dev/null +++ b/libltdl/aclocal.m4 @@ -0,0 +1,566 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + + +# serial 40 AC_PROG_LIBTOOL +AC_DEFUN(AC_PROG_LIBTOOL, +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl + +# Save cache, so that ltconfig can load it +AC_CACHE_SAVE + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ +LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ +DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| AC_MSG_ERROR([libtool configure failed]) + +# Reload cache, that may have been modified by ltconfig +AC_CACHE_LOAD + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log +]) + +AC_DEFUN(AC_LIBTOOL_SETUP, +[AC_PREREQ(2.13)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +dnl + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" +ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], +[libtool_flags="$libtool_flags --enable-dlopen"]) +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[libtool_flags="$libtool_flags --enable-win32-dll"]) +AC_ARG_ENABLE(libtool-lock, + [ --disable-libtool-lock avoid locking (might break parallel builds)]) +test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock" +test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +]) +esac +]) + +# AC_LIBTOOL_DLOPEN - enable checks for dlopen support +AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) + +# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's +AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) + +# AC_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AC_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_SHARED, [dnl +define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl +]) + +# AC_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no)]) + +# AC_ENABLE_STATIC - implement the --enable-static flag +# Usage: AC_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_STATIC, [dnl +define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AC_ENABLE_STATIC_DEFAULT)dnl +]) + +# AC_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no)]) + + +# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag +# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl +define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(fast-install, +changequote(<<, >>)dnl +<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl +]) + +# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install +AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no)]) + +# AC_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN(AC_PROG_LD, +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. +changequote(,)dnl + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' +changequote([,])dnl + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_SUBST(LD) +AC_PROG_LD_GNU +]) + +AC_DEFUN(AC_PROG_LD_GNU, +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +]) + +# AC_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN(AC_PROG_NM, +[AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(ac_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi]) +NM="$ac_cv_path_NM" +AC_MSG_RESULT([$NM]) +AC_SUBST(NM) +]) + +# AC_CHECK_LIBM - check for math library +AC_DEFUN(AC_CHECK_LIBM, +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case "$host" in +*-*-beos* | *-*-cygwin*) + # These system don't have libm + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, main, LIBM="-lm") + ;; +esac +]) + +# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl convenience library, adds --enable-ltdl-convenience to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case "$enable_ltdl_convenience" in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la + INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) +]) + +# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl installable library, and adds --enable-ltdl-install to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, main, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la + INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + INCLTDL= + fi +]) + +dnl old names +AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl +AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl +AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl +AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl +AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl +AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl +AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl + +dnl This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL])dnl + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<<am_indx=1 +for am_file in <<$1>>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + diff --git a/libltdl/config.h.in b/libltdl/config.h.in new file mode 100644 index 00000000..1e7613ef --- /dev/null +++ b/libltdl/config.h.in @@ -0,0 +1,80 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define if you have the dlerror function. */ +#undef HAVE_DLERROR + +/* Define if you have the index function. */ +#undef HAVE_INDEX + +/* Define if you have the rindex function. */ +#undef HAVE_RINDEX + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the strrchr function. */ +#undef HAVE_STRRCHR + +/* Define if you have the <ctype.h> header file. */ +#undef HAVE_CTYPE_H + +/* Define if you have the <dl.h> header file. */ +#undef HAVE_DL_H + +/* Define if you have the <dld.h> header file. */ +#undef HAVE_DLD_H + +/* Define if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define if you have the <malloc.h> header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + +/* Define if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to the extension used for shared libraries, say, .so. */ +#undef LTDL_SHLIB_EXT + +/* Define to the name of the environment variable that determines the dynamic library search path. */ +#undef LTDL_SHLIBPATH_VAR + +/* Define to the sub-directory in which libtool stores uninstalled libraries. */ +#undef LTDL_OBJDIR + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define if dlsym() requires a leading underscode in symbol names. */ +#undef NEED_USCORE + diff --git a/libltdl/configure b/libltdl/configure new file mode 100755 index 00000000..91329a88 --- /dev/null +++ b/libltdl/configure @@ -0,0 +1,3077 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" +ac_help="$ac_help + --enable-shared[=PKGS] build shared libraries [default=yes]" +ac_help="$ac_help + --enable-static[=PKGS] build static libraries [default=yes]" +ac_help="$ac_help + --enable-fast-install[=PKGS] optimize for fast installation [default=yes]" +ac_help="$ac_help + --with-gnu-ld assume the C compiler uses GNU ld [default=no]" +ac_help="$ac_help + --disable-libtool-lock avoid locking (might break parallel builds)" +ac_help="$ac_help + --enable-ltdl-install install libltdl" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=ltdl.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then + if test -f ${srcdir}/ltconfig && test -f ${srcdir}/ltmain.sh; then + # if libltdl is libtoolized, it is assumed to be stand-alone and + # installed unless the command line overrides it (tested above) + enable_ltdl_install=yes + else + echo "configure: warning: *** The top-level configure must select either" 1>&2 + echo "configure: warning: *** A""C_LIBLTDL_INSTALLABLE or A""C_LIBLTDL_CONVENIENCE." 1>&2 + { echo "configure: error: *** Maybe you want to --enable-ltdl-install?" 1>&2; exit 1; } + fi +fi + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:584: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:637: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:694: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=libltdl + +VERSION=1.0 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 +echo "configure:733: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:746: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:759: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:772: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:785: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + + + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:802: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:828: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:858: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:909: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:941: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 952 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:957: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:983: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:988: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:997: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1016: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1048: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1053 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1102: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1123: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <<EOF +#line 1130 "configure" +#include "confdefs.h" + +int main() { +} $ac_kw foo() { +; return 0; } +EOF +if { (eval echo configure:1137: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <<EOF +#define inline $ac_cv_c_inline +EOF + ;; +esac + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_shared=yes +fi + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_static=yes +fi + +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_fast_install=yes +fi + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1238: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1259: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1279: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 +echo "configure:1318: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 +echo "configure:1342: checking for GNU ld" >&5 +else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 +echo "configure:1345: checking for non-GNU ld" >&5 +fi +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } + +echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 +echo "configure:1381: checking if the linker ($LD) is GNU ld" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 + + +echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 +echo "configure:1397: checking for BSD-compatible nm" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi +fi + +NM="$ac_cv_path_NM" +echo "$ac_t""$NM" 1>&6 + + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1434: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + : +fi + +test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock" +test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 1478 "configure"' > conftest.$ac_ext + if { (eval echo configure:1479: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 +echo "configure:1500: checking whether the C compiler needs -belf" >&5 +if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1505 "configure" +#include "confdefs.h" + +int main() { + +; return 0; } +EOF +if { (eval echo configure:1512: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + lt_cv_cc_needs_belf=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + lt_cv_cc_needs_belf=no +fi +rm -f conftest* +fi + +echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + + +esac + + +# Save cache, so that ltconfig can load it +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ +LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ +DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + +# Reload cache, that may have been modified by ltconfig +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log + + + +# Check whether --enable-ltdl-install or --disable-ltdl-install was given. +if test "${enable_ltdl_install+set}" = set; then + enableval="$enable_ltdl_install" + : +fi + + + + +if test x"${enable_ltdl_install-no}" != xno; then + INSTALL_LTDL_TRUE= + INSTALL_LTDL_FALSE='#' +else + INSTALL_LTDL_TRUE='#' + INSTALL_LTDL_FALSE= +fi + + +if test x"${enable_ltdl_convenience-no}" != xno; then + CONVENIENCE_LTDL_TRUE= + CONVENIENCE_LTDL_FALSE='#' +else + CONVENIENCE_LTDL_TRUE='#' + CONVENIENCE_LTDL_FALSE= +fi + +rm -f conftest +./libtool --config > conftest +. ./conftest +rm -f conftest + +echo $ac_n "checking which extension is used for shared libraries""... $ac_c" 1>&6 +echo "configure:1647: checking which extension is used for shared libraries" >&5 +if eval "test \"`echo '$''{'libltdl_cv_shlibext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ( + last= + for spec in $library_names_spec; do + last="$spec" + done + + echo "$last" | sed 's/\[.*\]//;s/^[^.]*//;s/\$.*$//;s/\.$//' > conftest + +) +libltdl_cv_shlibext=`cat conftest` +rm -f conftest + +fi + +echo "$ac_t""$libltdl_cv_shlibext" 1>&6 +if test -n "$libltdl_cv_shlibext"; then + cat >> confdefs.h <<EOF +#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" +EOF + +fi + +echo $ac_n "checking which variable specifies run-time library path""... $ac_c" 1>&6 +echo "configure:1674: checking which variable specifies run-time library path" >&5 +if eval "test \"`echo '$''{'libltdl_cv_shlibpath_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + libltdl_cv_shlibpath_var="$shlibpath_var" +fi + +echo "$ac_t""$libltdl_cv_shlibpath_var" 1>&6 +if test -n "$libltdl_cv_shlibpath_var"; then + cat >> confdefs.h <<EOF +#define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" +EOF + +fi + +echo $ac_n "checking for objdir""... $ac_c" 1>&6 +echo "configure:1690: checking for objdir" >&5 +if eval "test \"`echo '$''{'libltdl_cv_objdir'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + libltdl_cv_objdir="$objdir" +fi + +echo "$ac_t""$libltdl_cv_objdir" 1>&6 +test -z "$libltdl_cv_objdir" && libltdl_cv_objdir=".libs" +cat >> confdefs.h <<EOF +#define LTDL_OBJDIR "$libltdl_cv_objdir/" +EOF + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1705: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 1720 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1726: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 1737 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1743: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 1754 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1760: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1785: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1790 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1815 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1833 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 1854 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in malloc.h memory.h stdlib.h stdio.h ctype.h dlfcn.h dl.h dld.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1892: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1897 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1902: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in string.h strings.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1932: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1937 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1942: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + break +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in strchr index +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1971: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1976 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + break +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in strrchr rindex +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2026: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2031 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2054: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + break +else + echo "$ac_t""no" 1>&6 +fi +done + + +echo $ac_n "checking whether libtool supports -dlopen/-dlpreopen""... $ac_c" 1>&6 +echo "configure:2080: checking whether libtool supports -dlopen/-dlpreopen" >&5 +if eval "test \"`echo '$''{'libltdl_cv_preloaded_symbols'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + +fi + +echo "$ac_t""$libltdl_cv_preloaded_symbols" 1>&6 +if test x"$libltdl_cv_preloaded_symbols" = x"yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_PRELOADED_SYMBOLS 1 +EOF + +fi + +LIBADD_DL= +echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 +echo "configure:2102: checking for dlopen in -ldl" >&5 +ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2110 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen(); + +int main() { +dlopen() +; return 0; } +EOF +if { (eval echo configure:2121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LIBDL 1 +EOF + LIBADD_DL="-ldl" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dlopen""... $ac_c" 1>&6 +echo "configure:2143: checking for dlopen" >&5 +if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2148 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +dlopen(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2171: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_dlopen=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_dlopen=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LIBDL 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for shl_load""... $ac_c" 1>&6 +echo "configure:2196: checking for shl_load" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2201 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +shl_load(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2224: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shl_load=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shl_load=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SHL_LOAD 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 +echo "configure:2245: checking for shl_load in -ldld" >&5 +ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2253 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load(); + +int main() { +shl_load() +; return 0; } +EOF +if { (eval echo configure:2264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SHL_LOAD 1 +EOF + LIBADD_DL="$LIBADD_DL -ldld" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 +echo "configure:2290: checking for dld_link in -ldld" >&5 +ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2298 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dld_link(); + +int main() { +dld_link() +; return 0; } +EOF +if { (eval echo configure:2309: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_DLD 1 +EOF +test "x$ac_cv_lib_dld_shl_load" = yes || LIBADD_DL="$LIBADD_DL -ldld" +else + echo "$ac_t""no" 1>&6 +fi + + + +if test "x$ac_cv_func_dlopen" = xyes || test "x$ac_cv_lib_dl_dlopen" = xyes; then + LIBS_SAVE="$LIBS" + LIBS="$LIBS $LIBADD_DL" + for ac_func in dlerror +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2340: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2345 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2368: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + LIBS="$LIBS_SAVE" +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6 +echo "configure:2397: checking command to parse $NM output" >&5 +if eval "test \"`echo '$''{'ac_cv_sys_global_symbol_pipe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # These are sane defaults that work on at least a few old systems. +# {They come from Ultrix. What could be older than Ultrix?!! ;)} + +# Character class describing NM global symbol codes. +ac_symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +ac_symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + ac_symcode='[BCDT]' + ;; +cygwin* | mingw*) + ac_symcode='[ABCDGISTW]' + ;; +hpux*) + ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + ac_symcode='[BCDEGRST]' + ;; +solaris*) + ac_symcode='[BDT]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + ac_symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.* \($ac_symcode\) *\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'" + + # Check to see that the pipe works correctly. + ac_pipe_works=no + rm -f conftest.$ac_ext + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func;return 0;} +EOF + + if { (eval echo configure:2460: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + + if { (eval echo configure:2464: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then + + # Try sorting and uniquifying the output. + if sort "$ac_nlist" | uniq > "$ac_nlist"T; then + mv -f "$ac_nlist"T "$ac_nlist" + else + rm -f "$ac_nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then + if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c' + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + ac_save_LIBS="$LIBS" + ac_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo configure:2516: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_pipe_works=yes + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$ac_save_LIBS" + CFLAGS="$ac_save_CFLAGS" + else + echo "cannot find nm_test_func in $ac_nlist" >&5 + fi + else + echo "cannot find nm_test_var in $ac_nlist" >&5 + fi + else + echo "cannot run $ac_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$ac_pipe_works" = yes; then + if test x"$ac_symprfx" = x"_"; then + ac_cv_sys_symbol_underscore=yes + else + ac_cv_sys_symbol_underscore=no + fi + break + else + ac_cv_sys_global_symbol_pipe= + fi +done + +fi + + +ac_result=yes +if test -z "$ac_cv_sys_global_symbol_pipe"; then + ac_result=no +fi +echo "$ac_t""$ac_result" 1>&6 + +echo $ac_n "checking for _ prefix in compiled symbols""... $ac_c" 1>&6 +echo "configure:2562: checking for _ prefix in compiled symbols" >&5 +if eval "test \"`echo '$''{'ac_cv_sys_symbol_underscore'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_sys_symbol_underscore=no +cat > conftest.$ac_ext <<EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +EOF +if { (eval echo configure:2571: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { (eval echo configure:2574: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&5 + fi +else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 +fi +rm -rf conftest* + +fi + +echo "$ac_t""$ac_cv_sys_symbol_underscore" 1>&6 + +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$ac_cv_func_dlopen" = xyes || + test x"$ac_cv_lib_dl_dlopen" = xyes ; then + echo $ac_n "checking whether we have to add an underscore for dlsym""... $ac_c" 1>&6 +echo "configure:2602: checking whether we have to add an underscore for dlsym" >&5 +if eval "test \"`echo '$''{'libltdl_cv_need_uscore'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + libltdl_cv_need_uscore=cross + +else + cat > conftest.$ac_ext <<EOF +#line 2611 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 && !ptr2) exit(0); } exit(1); } + +EOF +if { (eval echo configure:2658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + libltdl_cv_need_uscore=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + libltdl_cv_need_uscore=yes +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$libltdl_cv_need_uscore" 1>&6 + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + cat >> confdefs.h <<\EOF +#define NEED_USCORE 1 +EOF + +fi + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CC@%$CC%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@RANLIB@%$RANLIB%g +s%@LD@%$LD%g +s%@NM@%$NM%g +s%@LN_S@%$LN_S%g +s%@LIBTOOL@%$LIBTOOL%g +s%@LIBTOOL_DEPS@%$LIBTOOL_DEPS%g +s%@INSTALL_LTDL_TRUE@%$INSTALL_LTDL_TRUE%g +s%@INSTALL_LTDL_FALSE@%$INSTALL_LTDL_FALSE%g +s%@CONVENIENCE_LTDL_TRUE@%$CONVENIENCE_LTDL_TRUE%g +s%@CONVENIENCE_LTDL_FALSE@%$CONVENIENCE_LTDL_FALSE%g +s%@CPP@%$CPP%g +s%@LIBADD_DL@%$LIBADD_DL%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="config.h" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <<EOF + + +EOF +cat >> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/libltdl/configure.in b/libltdl/configure.in new file mode 100644 index 00000000..10233c6c --- /dev/null +++ b/libltdl/configure.in @@ -0,0 +1,373 @@ +dnl Process this file with autoconf to create configure. + +AC_INIT(ltdl.c) + +if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then + if test -f ${srcdir}/ltconfig && test -f ${srcdir}/ltmain.sh; then + # if libltdl is libtoolized, it is assumed to be stand-alone and + # installed unless the command line overrides it (tested above) + enable_ltdl_install=yes + else + AC_MSG_WARN([*** The top-level configure must select either]) + AC_MSG_WARN([*** [A""C_LIBLTDL_INSTALLABLE] or [A""C_LIBLTDL_CONVENIENCE].]) + AC_MSG_ERROR([*** Maybe you want to --enable-ltdl-install?]) + fi +fi + +AM_INIT_AUTOMAKE(libltdl,1.0,-) +AM_CONFIG_HEADER(config.h) +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_C_CONST +AC_C_INLINE +AM_PROG_LIBTOOL +AC_SUBST(LIBTOOL_DEPS) + +AC_ARG_ENABLE(ltdl-install, +[ --enable-ltdl-install install libltdl]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) + +dnl Read the libtool configuration +rm -f conftest +./libtool --config > conftest +. ./conftest +rm -f conftest + +AC_CACHE_CHECK([which extension is used for shared libraries], + libltdl_cv_shlibext, [dnl +( + last= + for spec in $library_names_spec; do + last="$spec" + done +changequote(, ) + echo "$last" | sed 's/\[.*\]//;s/^[^.]*//;s/\$.*$//;s/\.$//' > conftest +changequote([, ]) +) +libltdl_cv_shlibext=`cat conftest` +rm -f conftest +]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED(LTDL_SHLIB_EXT, "$libltdl_cv_shlibext", + [Define to the extension used for shared libraries, say, ".so". ]) +fi + +AC_CACHE_CHECK([which variable specifies run-time library path], + libltdl_cv_shlibpath_var, [libltdl_cv_shlibpath_var="$shlibpath_var"]) +if test -n "$libltdl_cv_shlibpath_var"; then + AC_DEFINE_UNQUOTED(LTDL_SHLIBPATH_VAR, "$libltdl_cv_shlibpath_var", + [Define to the name of the environment variable that determines the dynamic library search path. ]) +fi + +AC_CACHE_CHECK([for objdir], + libltdl_cv_objdir, [libltdl_cv_objdir="$objdir"]) +test -z "$libltdl_cv_objdir" && libltdl_cv_objdir=".libs" +AC_DEFINE_UNQUOTED(LTDL_OBJDIR, "$libltdl_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries. ]) + +AC_HEADER_STDC +AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dlfcn.h dl.h dld.h) +AC_CHECK_HEADERS(string.h strings.h, break) +AC_CHECK_FUNCS(strchr index, break) +AC_CHECK_FUNCS(strrchr rindex, break) + +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + libltdl_cv_preloaded_symbols, [dnl + if test -n "$global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi +]) +if test x"$libltdl_cv_preloaded_symbols" = x"yes"; then + AC_DEFINE(HAVE_PRELOADED_SYMBOLS, 1, + [Define if libtool can extract symbol lists from object files. ]) +fi + +LIBADD_DL= +AC_CHECK_LIB(dl, dlopen, [AC_DEFINE(HAVE_LIBDL, 1) LIBADD_DL="-ldl"], +[AC_CHECK_FUNC(dlopen, [AC_DEFINE(HAVE_LIBDL, 1)])]) +AC_CHECK_FUNC(shl_load, [AC_DEFINE(HAVE_SHL_LOAD, 1)], +[AC_CHECK_LIB(dld, shl_load, [AC_DEFINE(HAVE_SHL_LOAD, 1) LIBADD_DL="$LIBADD_DL -ldld"])]) +AC_CHECK_LIB(dld, dld_link, [AC_DEFINE(HAVE_DLD, 1)dnl +test "x$ac_cv_lib_dld_shl_load" = yes || LIBADD_DL="$LIBADD_DL -ldld"]) +AC_SUBST(LIBADD_DL) + +if test "x$ac_cv_func_dlopen" = xyes || test "x$ac_cv_lib_dl_dlopen" = xyes; then + LIBS_SAVE="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS(dlerror) + LIBS="$LIBS_SAVE" +fi + +dnl Check for command to grab the raw symbol name followed +dnl by C symbol name from nm. +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_NM])dnl +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output]) +AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe, +[# These are sane defaults that work on at least a few old systems. +# {They come from Ultrix. What could be older than Ultrix?!! ;)} + +changequote(,)dnl +# Character class describing NM global symbol codes. +ac_symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +ac_symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + ac_symcode='[BCDT]' + ;; +cygwin* | mingw*) + ac_symcode='[ABCDGISTW]' + ;; +hpux*) + ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + ac_symcode='[BCDEGRST]' + ;; +solaris*) + ac_symcode='[BDT]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + ac_symcode='[ABCDGISTW]' +fi +changequote([,])dnl + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($ac_symcode\)[ ][ ]*\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'" + + # Check to see that the pipe works correctly. + ac_pipe_works=no + rm -f conftest.$ac_ext + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func;return 0;} +EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + + if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + + # Try sorting and uniquifying the output. + if sort "$ac_nlist" | uniq > "$ac_nlist"T; then + mv -f "$ac_nlist"T "$ac_nlist" + else + rm -f "$ac_nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then + if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c' + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +changequote(,)dnl +lt_preloaded_symbols[] = +changequote([,])dnl +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + ac_save_LIBS="$LIBS" + ac_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if AC_TRY_EVAL(ac_link) && test -s conftest; then + ac_pipe_works=yes + else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + LIBS="$ac_save_LIBS" + CFLAGS="$ac_save_CFLAGS" + else + echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + else + echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC + fi + else + echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi + else + echo "$progname: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$ac_pipe_works" = yes; then + if test x"$ac_symprfx" = x"_"; then + ac_cv_sys_symbol_underscore=yes + else + ac_cv_sys_symbol_underscore=no + fi + break + else + ac_cv_sys_global_symbol_pipe= + fi +done +]) + +ac_result=yes +if test -z "$ac_cv_sys_global_symbol_pipe"; then + ac_result=no +fi +AC_MSG_RESULT($ac_result) + +dnl does the compiler prefix global symbols with an underscore? +AC_MSG_CHECKING([for _ prefix in compiled symbols]) +AC_CACHE_VAL(ac_cv_sys_symbol_underscore, +[ac_cv_sys_symbol_underscore=no +cat > conftest.$ac_ext <<EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +EOF +if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + fi + else + echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC +fi +rm -rf conftest* +]) +AC_MSG_RESULT($ac_cv_sys_symbol_underscore) + +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$ac_cv_func_dlopen" = xyes || + test x"$ac_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + libltdl_cv_need_uscore, [dnl + AC_TRY_RUN([ +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 && !ptr2) exit(0); } exit(1); } +], libltdl_cv_need_uscore=no, libltdl_cv_need_uscore=yes, + libltdl_cv_need_uscore=cross +)]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE(NEED_USCORE, 1, + [Define if dlsym() requires a leading underscode in symbol names. ]) +fi + +dnl Output the makefile +AC_OUTPUT(Makefile) + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c new file mode 100644 index 00000000..ce37e27e --- /dev/null +++ b/libltdl/ltdl.c @@ -0,0 +1,1577 @@ +/* ltdl.c -- system independent dlopen wrapper + Copyright (C) 1998-1999 Free Software Foundation, Inc. + Originally by Thomas Tanner <tanner@gmx.de> + This file is part of GNU Libtool. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Library General Public License, +if you distribute this file as part of a program that uses GNU libtool +to create libraries and programs, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define _LTDL_COMPILE_ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#if HAVE_STRING_H +#include <string.h> +#endif + +#if HAVE_STRINGS_H +#include <strings.h> +#endif + +#if HAVE_CTYPE_H +#include <ctype.h> +#endif + +#if HAVE_MALLOC_H +#include <malloc.h> +#endif + +#if HAVE_MEMORY_H +#include <memory.h> +#endif + +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#if HAVE_STDIO_H +#include <stdio.h> +#endif + +#include "ltdl.h" + +/* max. filename length */ +#ifndef LTDL_FILENAME_MAX +#define LTDL_FILENAME_MAX 1024 +#endif + +#undef LTDL_READTEXT_MODE +/* fopen() mode flags for reading a text file */ +#ifdef _WIN32 +#define LTDL_READTEXT_MODE "rt" +#else +#define LTDL_READTEXT_MODE "r" +#endif + +#undef LTDL_SYMBOL_LENGTH +/* This is the maximum symbol size that won't require malloc/free */ +#define LTDL_SYMBOL_LENGTH 128 + +#undef LTDL_SYMBOL_OVERHEAD +/* This accounts for the _LTX_ separator */ +#define LTDL_SYMBOL_OVERHEAD 5 + +static const char objdir[] = LTDL_OBJDIR; +#ifdef LTDL_SHLIB_EXT +static const char shlib_ext[] = LTDL_SHLIB_EXT; +#endif + +static const char unknown_error[] = "unknown error"; +static const char dlopen_not_supported_error[] = "dlopen support not available"; +static const char file_not_found_error[] = "file not found"; +static const char no_symbols_error[] = "no symbols defined"; +static const char cannot_open_error[] = "can't open the module"; +static const char cannot_close_error[] = "can't close the module"; +static const char symbol_error[] = "symbol not found"; +static const char memory_error[] = "not enough memory"; +static const char invalid_handle_error[] = "invalid handle"; +static const char buffer_overflow_error[] = "internal buffer overflow"; +static const char shutdown_error[] = "library already shutdown"; + +#ifndef HAVE_PRELOADED_SYMBOLS +/* If libtool won't define it, we'd better do */ +const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } }; +#endif + +static const char *last_error = 0; + +lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc; +void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free; + +typedef struct lt_dltype_t { + struct lt_dltype_t *next; + const char *sym_prefix; /* prefix for symbols */ + int (*mod_init) LTDL_PARAMS((void)); + int (*mod_exit) LTDL_PARAMS((void)); + int (*lib_open) LTDL_PARAMS((lt_dlhandle handle, const char *filename)); + int (*lib_close) LTDL_PARAMS((lt_dlhandle handle)); + lt_ptr_t (*find_sym) LTDL_PARAMS((lt_dlhandle handle, const char *symbol)); +} lt_dltype_t; + +#define LTDL_TYPE_TOP 0 + +typedef struct lt_dlhandle_t { + struct lt_dlhandle_t *next; + lt_dltype_t *type; /* dlopening interface */ + char *filename; /* file name */ + char *name; /* module name */ + int usage; /* usage */ + int depcount; /* number of dependencies */ + lt_dlhandle *deplibs; /* dependencies */ + lt_ptr_t handle; /* system handle */ + lt_ptr_t system; /* system specific data */ +} lt_dlhandle_t; + +#undef strdup +#define strdup xstrdup + +static inline char * +strdup(str) + const char *str; +{ + char *tmp; + + if (!str) + return 0; + tmp = (char*) lt_dlmalloc(strlen(str)+1); + if (tmp) + strcpy(tmp, str); + return tmp; +} + +#if ! HAVE_STRCHR + +# if HAVE_INDEX + +# define strchr index + +# else + +# define strchr xstrchr + +static inline const char* +strchr(str, ch) + const char *str; + int ch; +{ + const char *p; + + for (p = str; *p != (char)ch && p != '\0'; p++) + /*NOWORK*/; + + return (*p == (char)ch) ? p : 0; +} + +# endif + +#endif + +#if ! HAVE_STRRCHR + +# if HAVE_RINDEX + +# define strrchr rindex + +# else + +# define strrchr xstrrchr + +static inline const char* +strrchr(str, ch) + const char *str; + int ch; +{ + const char *p; + + for (p = str; p != '\0'; p++) + /*NOWORK*/; + + while (*p != (char)ch && p >= str) + p--; + + return (*p == (char)ch) ? p : 0; +} + +# endif + +#endif + +#if HAVE_LIBDL + +/* dynamic linking with dlopen/dlsym */ + +#if HAVE_DLFCN_H +# include <dlfcn.h> +#endif + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +static int +sys_dl_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dl_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dl_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW); + if (!handle->handle) { +#if HAVE_DLERROR + last_error = dlerror(); +#else + last_error = cannot_open_error; +#endif + return 1; + } + return 0; +} + +static int +sys_dl_close (handle) + lt_dlhandle handle; +{ + if (dlclose(handle->handle) != 0) { +#if HAVE_DLERROR + last_error = dlerror(); +#else + last_error = cannot_close_error; +#endif + return 1; + } + return 0; +} + +static lt_ptr_t +sys_dl_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = dlsym(handle->handle, symbol); + + if (!address) +#if HAVE_DLERROR + last_error = dlerror(); +#else + last_error = symbol_error; +#endif + return address; +} + +static +lt_dltype_t +#ifdef NEED_USCORE +sys_dl = { LTDL_TYPE_TOP, "_", sys_dl_init, sys_dl_exit, + sys_dl_open, sys_dl_close, sys_dl_sym }; +#else +sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit, + sys_dl_open, sys_dl_close, sys_dl_sym }; +#endif + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_dl + +#endif + +#if HAVE_SHL_LOAD + +/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ + +#ifdef HAVE_DL_H +#include <dl.h> +#endif + +/* some flags are missing on some systems, so we provide + * harmless defaults. + * + * Mandatory: + * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. + * BIND_DEFERRED - Delay code symbol resolution until actual reference. + * + * Optionally: + * BIND_FIRST - Place the library at the head of the symbol search order. + * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all unsatisfied + * symbols as fatal. This flag allows binding of unsatisfied code + * symbols to be deferred until use. + * [Perl: For certain libraries, like DCE, deferred binding often + * causes run time problems. Adding BIND_NONFATAL to BIND_IMMEDIATE + * still allows unresolved references in situations like this.] + * BIND_NOSTART - Do not call the initializer for the shared library when the + * library is loaded, nor on a future call to shl_unload(). + * BIND_VERBOSE - Print verbose messages concerning possible unsatisfied symbols. + * + * hp9000s700/hp9000s800: + * BIND_RESTRICTED - Restrict symbols visible by the library to those present at + * library load time. + * DYNAMIC_PATH - Allow the loader to dynamically search for the library specified + * by the path argument. + */ + +#ifndef DYNAMIC_PATH +#define DYNAMIC_PATH 0 +#endif /* DYNAMIC_PATH */ +#ifndef BIND_RESTRICTED +#define BIND_RESTRICTED 0 +#endif /* BIND_RESTRICTED */ + +#define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE | DYNAMIC_PATH) + +static int +sys_shl_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_shl_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_shl_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = shl_load(filename, LTDL_BIND_FLAGS, 0L); + if (!handle->handle) { + last_error = cannot_open_error; + return 1; + } + return 0; +} + +static int +sys_shl_close (handle) + lt_dlhandle handle; +{ + if (shl_unload((shl_t) (handle->handle)) != 0) { + last_error = cannot_close_error; + return 1; + } + return 0; +} + +static lt_ptr_t +sys_shl_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address; + + if (handle->handle && shl_findsym((shl_t*) &(handle->handle), + symbol, TYPE_UNDEFINED, &address) == 0) + if (address) + return address; + last_error = symbol_error; + return 0; +} + +static +lt_dltype_t +sys_shl = { LTDL_TYPE_TOP, 0, sys_shl_init, sys_shl_exit, + sys_shl_open, sys_shl_close, sys_shl_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_shl + +#endif + +#if HAVE_DLD + +/* dynamic linking with dld */ + +#if HAVE_DLD_H +#include <dld.h> +#endif + +static int +sys_dld_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dld_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dld_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = strdup(filename); + if (!handle->handle) { + last_error = memory_error; + return 1; + } + if (dld_link(filename) != 0) { + last_error = cannot_open_error; + lt_dlfree(handle->handle); + return 1; + } + return 0; +} + +static int +sys_dld_close (handle) + lt_dlhandle handle; +{ + if (dld_unlink_by_file((char*)(handle->handle), 1) != 0) { + last_error = cannot_close_error; + return 1; + } + lt_dlfree(handle->filename); + return 0; +} + +static lt_ptr_t +sys_dld_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = dld_get_func(symbol); + + if (!address) + last_error = symbol_error; + return address; +} + +static +lt_dltype_t +sys_dld = { LTDL_TYPE_TOP, 0, sys_dld_init, sys_dld_exit, + sys_dld_open, sys_dld_close, sys_dld_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_dld + +#endif + +#ifdef _WIN32 + +/* dynamic linking for Win32 */ + +#include <windows.h> + +static int +sys_wll_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_wll_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_wll_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = LoadLibrary(filename); + if (!handle->handle) { + last_error = cannot_open_error; + return 1; + } + return 0; +} + +static int +sys_wll_close (handle) + lt_dlhandle handle; +{ + if (FreeLibrary(handle->handle) != 0) { + last_error = cannot_close_error; + return 1; + } + return 0; +} + +static lt_ptr_t +sys_wll_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = GetProcAddress(handle->handle, symbol); + + if (!address) + last_error = symbol_error; + return address; +} + +static +lt_dltype_t +sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit, + sys_wll_open, sys_wll_close, sys_wll_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_wll + +#endif + +#ifdef __BEOS__ + +/* dynamic linking for BeOS */ + +#include <kernel/image.h> + +static int +sys_bedl_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_bedl_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_bedl_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + image_id image = 0; + + if (filename) { + image = load_add_on(filename); + } else { + image_info info; + int32 cookie = 0; + if (get_next_image_info(0, &cookie, &info) == B_OK) + image = load_add_on(info.name); + } + if (image <= 0) { + last_error = cannot_open_error; + return 1; + } + handle->handle = (void*) image; + return 0; +} + +static int +sys_bedl_close (handle) + lt_dlhandle handle; +{ + if (unload_add_on((image_id)handle->handle) != B_OK) { + last_error = cannot_close_error; + return 1; + } + return 0; +} + +static lt_ptr_t +sys_bedl_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = 0; + image_id image = (image_id)handle->handle; + + if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY, + &address) != B_OK) { + last_error = symbol_error; + return 0; + } + return address; +} + +static +lt_dltype_t +sys_bedl = { LTDL_TYPE_TOP, 0, sys_bedl_init, sys_bedl_exit, + sys_bedl_open, sys_bedl_close, sys_bedl_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_bedl + +#endif + +/* emulate dynamic linking using preloaded_symbols */ + +typedef struct lt_dlsymlists_t { + struct lt_dlsymlists_t *next; + const lt_dlsymlist *syms; +} lt_dlsymlists_t; + +static const lt_dlsymlist *default_preloaded_symbols = 0; +static lt_dlsymlists_t *preloaded_symbols = 0; + +static int +presym_init LTDL_PARAMS((void)) +{ + preloaded_symbols = 0; + if (default_preloaded_symbols) + return lt_dlpreload(default_preloaded_symbols); + return 0; +} + +static int +presym_free_symlists LTDL_PARAMS((void)) +{ + lt_dlsymlists_t *lists = preloaded_symbols; + + while (lists) { + lt_dlsymlists_t *tmp = lists; + + lists = lists->next; + lt_dlfree(tmp); + } + preloaded_symbols = 0; + return 0; +} + +static int +presym_exit LTDL_PARAMS((void)) +{ + presym_free_symlists(); + return 0; +} + +static int +presym_add_symlist (preloaded) + const lt_dlsymlist *preloaded; +{ + lt_dlsymlists_t *tmp; + lt_dlsymlists_t *lists = preloaded_symbols; + + while (lists) { + if (lists->syms == preloaded) + return 0; + lists = lists->next; + } + + tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t)); + if (!tmp) { + last_error = memory_error; + return 1; + } + tmp->syms = preloaded; + tmp->next = 0; + if (!preloaded_symbols) + preloaded_symbols = tmp; + else { + /* append to the end */ + lists = preloaded_symbols; + while (lists->next) + lists = lists->next; + lists->next = tmp; + } + return 0; +} + +static int +presym_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + lt_dlsymlists_t *lists = preloaded_symbols; + + if (!lists) { + last_error = no_symbols_error; + return 1; + } + if (!filename) + filename = "@PROGRAM@"; + while (lists) { + const lt_dlsymlist *syms = lists->syms; + + while (syms->name) { + if (!syms->address && + strcmp(syms->name, filename) == 0) { + handle->handle = (lt_ptr_t) syms; + return 0; + } + syms++; + } + lists = lists->next; + } + last_error = file_not_found_error; + return 1; +} + +static int +presym_close (handle) + lt_dlhandle handle; +{ + /* Just to silence gcc -Wall */ + handle = 0; + return 0; +} + +static lt_ptr_t +presym_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_dlsymlist *syms = (lt_dlsymlist*)(handle->handle); + + syms++; + while (syms->address) { + if (strcmp(syms->name, symbol) == 0) + return syms->address; + syms++; + } + last_error = symbol_error; + return 0; +} + +static +lt_dltype_t +presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit, + presym_open, presym_close, presym_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &presym + +static char *user_search_path = 0; +static lt_dlhandle handles = 0; +static int initialized = 0; + +static lt_dltype_t *types = LTDL_TYPE_TOP; +#undef LTDL_TYPE_TOP + +int +lt_dlinit LTDL_PARAMS((void)) +{ + /* initialize libltdl */ + lt_dltype_t **type = &types; + int typecount = 0; + + if (initialized) { /* Initialize only at first call. */ + initialized++; + return 0; + } + handles = 0; + user_search_path = 0; /* empty search path */ + + while (*type) { + if ((*type)->mod_init()) + *type = (*type)->next; /* Remove it from the list */ + else { + type = &(*type)->next; /* Keep it */ + typecount++; + } + } + if (typecount == 0) { + last_error = dlopen_not_supported_error; + return 1; + } + last_error = 0; + initialized = 1; + return 0; +} + +int +lt_dlpreload (preloaded) + const lt_dlsymlist *preloaded; +{ + if (preloaded) + return presym_add_symlist(preloaded); + presym_free_symlists(); + if (default_preloaded_symbols) + return lt_dlpreload(default_preloaded_symbols); + return 0; +} + +int +lt_dlpreload_default (preloaded) + const lt_dlsymlist *preloaded; +{ + default_preloaded_symbols = preloaded; + return 0; +} + +int +lt_dlexit LTDL_PARAMS((void)) +{ + /* shut down libltdl */ + lt_dltype_t *type = types; + int errors; + + if (!initialized) { + last_error = shutdown_error; + return 1; + } + if (initialized != 1) { /* shut down only at last call. */ + initialized--; + return 0; + } + /* close all modules */ + errors = 0; + while (handles) { + /* FIXME: what if a module depends on another one? */ + if (lt_dlclose(handles)) + errors++; + } + initialized = 0; + while (type) { + if (type->mod_exit()) + errors++; + type = type->next; + } + return errors; +} + +static int +tryall_dlopen (handle, filename) + lt_dlhandle *handle; + const char *filename; +{ + lt_dlhandle cur; + lt_dltype_t *type = types; + const char *saved_error = last_error; + + /* check whether the module was already opened */ + cur = handles; + while (cur) { + if (!cur->filename && !filename) + break; + if (cur->filename && filename && + strcmp(cur->filename, filename) == 0) + break; + cur = cur->next; + } + if (cur) { + cur->usage++; + *handle = cur; + return 0; + } + + cur = *handle; + if (filename) { + cur->filename = strdup(filename); + if (!cur->filename) { + last_error = memory_error; + return 1; + } + } else + cur->filename = 0; + while (type) { + if (type->lib_open(cur, filename) == 0) + break; + type = type->next; + } + if (!type) { + if (cur->filename) + lt_dlfree(cur->filename); + return 1; + } + cur->type = type; + last_error = saved_error; + return 0; +} + +static int +find_module (handle, dir, libdir, dlname, old_name, installed) + lt_dlhandle *handle; + const char *dir; + const char *libdir; + const char *dlname; + const char *old_name; + int installed; +{ + int error; + char *filename; + /* try to open the old library first; if it was dlpreopened, + we want the preopened version of it, even if a dlopenable + module is available */ + if (old_name && tryall_dlopen(handle, old_name) == 0) + return 0; + /* try to open the dynamic library */ + if (dlname) { + /* try to open the installed module */ + if (installed && libdir) { + filename = (char*) + lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1); + if (!filename) { + last_error = memory_error; + return 1; + } + strcpy(filename, libdir); + strcat(filename, "/"); + strcat(filename, dlname); + error = tryall_dlopen(handle, filename) == 0; + lt_dlfree(filename); + if (error) + return 0; + } + /* try to open the not-installed module */ + if (!installed) { + filename = (char*) + lt_dlmalloc((dir ? strlen(dir) : 0) + + strlen(objdir) + strlen(dlname) + 1); + if (!filename) { + last_error = memory_error; + return 1; + } + if (dir) + strcpy(filename, dir); + else + *filename = 0; + strcat(filename, objdir); + strcat(filename, dlname); + + error = tryall_dlopen(handle, filename) == 0; + lt_dlfree(filename); + if (error) + return 0; + } + /* hmm, maybe it was moved to another directory */ + { + filename = (char*) + lt_dlmalloc((dir ? strlen(dir) : 0) + + strlen(dlname) + 1); + if (dir) + strcpy(filename, dir); + else + *filename = 0; + strcat(filename, dlname); + error = tryall_dlopen(handle, filename) == 0; + lt_dlfree(filename); + if (error) + return 0; + } + } + last_error = file_not_found_error; + return 1; +} + +static lt_ptr_t +find_file (basename, search_path, pdir, handle) + const char *basename; + const char *search_path; + char **pdir; + lt_dlhandle *handle; +{ + /* when handle != NULL search a library, otherwise a file */ + /* return NULL on failure, otherwise the file/handle */ + + char *filename = 0; + int filenamesize = 0; + const char *next = search_path; + int lenbase = strlen(basename); + + if (!next || !*next) { + last_error = file_not_found_error; + return 0; + } + while (next) { + int lendir; + const char *cur = next; + + next = strchr(cur, ':'); + if (!next) + next = cur + strlen(cur); + lendir = next - cur; + if (*next == ':') + ++next; + else + next = 0; + if (lendir == 0) + continue; + if (lendir + 1 + lenbase >= filenamesize) { + if (filename) + lt_dlfree(filename); + filenamesize = lendir + 1 + lenbase + 1; + filename = (char*) lt_dlmalloc(filenamesize); + if (!filename) { + last_error = memory_error; + return 0; + } + } + strncpy(filename, cur, lendir); + if (filename[lendir-1] != '/') + filename[lendir++] = '/'; + strcpy(filename+lendir, basename); + if (handle) { + if (tryall_dlopen(handle, filename) == 0) { + lt_dlfree(filename); + return (lt_ptr_t) handle; + } + } else { + FILE *file = fopen(filename, LTDL_READTEXT_MODE); + if (file) { + if (*pdir) + lt_dlfree(*pdir); + filename[lendir] = '\0'; + *pdir = strdup(filename); + if (!*pdir) { + /* We could have even avoided the + strdup, but there would be some + memory overhead. */ + *pdir = filename; + } else + lt_dlfree(filename); + return (lt_ptr_t) file; + } + } + } + if (filename) + lt_dlfree(filename); + last_error = file_not_found_error; + return 0; +} + +static int +load_deplibs(handle, deplibs) + lt_dlhandle handle; + const char *deplibs; +{ + /* FIXME: load deplibs */ + handle->depcount = 0; + handle->deplibs = 0; + /* Just to silence gcc -Wall */ + deplibs = 0; + return 0; +} + +static int +unload_deplibs(handle) + lt_dlhandle handle; +{ + /* FIXME: unload deplibs */ + /* Just to silence gcc -Wall */ + handle = 0; + return 0; +} + +static inline int +trim (dest, str) + char **dest; + const char *str; +{ + /* remove the leading and trailing "'" from str + and store the result in dest */ + char *tmp; + char *end = strrchr(str, '\''); + int len = strlen(str); + + if (*dest) + lt_dlfree(*dest); + if (len > 3 && str[0] == '\'') { + tmp = (char*) lt_dlmalloc(end - str); + if (!tmp) { + last_error = memory_error; + return 1; + } + strncpy(tmp, &str[1], (end - str) - 1); + tmp[len-3] = '\0'; + *dest = tmp; + } else + *dest = 0; + return 0; +} + +static inline int +free_vars(dir, name, dlname, oldname, libdir, deplibs) + char *dir; + char *name; + char *dlname; + char *oldname; + char *libdir; + char *deplibs; +{ + if (dir) + lt_dlfree(dir); + if (name) + lt_dlfree(name); + if (dlname) + lt_dlfree(dlname); + if (oldname) + lt_dlfree(oldname); + if (libdir) + lt_dlfree(libdir); + if (deplibs) + lt_dlfree(deplibs); + return 0; +} + +lt_dlhandle +lt_dlopen (filename) + const char *filename; +{ + lt_dlhandle handle, newhandle; + const char *basename, *ext; + const char *saved_error = last_error; + char *dir = 0, *name = 0; + + if (!filename) { + handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t)); + if (!handle) { + last_error = memory_error; + return 0; + } + handle->usage = 0; + handle->depcount = 0; + handle->deplibs = 0; + newhandle = handle; + if (tryall_dlopen(&newhandle, 0) != 0) { + lt_dlfree(handle); + return 0; + } + goto register_handle; + } + basename = strrchr(filename, '/'); + if (basename) { + basename++; + dir = (char*) lt_dlmalloc(basename - filename + 1); + if (!dir) { + last_error = memory_error; + return 0; + } + strncpy(dir, filename, basename - filename); + dir[basename - filename] = '\0'; + } else + basename = filename; + /* check whether we open a libtool module (.la extension) */ + ext = strrchr(basename, '.'); + if (ext && strcmp(ext, ".la") == 0) { + /* this seems to be a libtool module */ + FILE *file; + int i; + char *dlname = 0, *old_name = 0; + char *libdir = 0, *deplibs = 0; + char *line; + int error = 0; + /* if we can't find the installed flag, it is probably an + installed libtool archive, produced with an old version + of libtool */ + int installed = 1; + + /* extract the module name from the file name */ + name = (char*) lt_dlmalloc(ext - basename + 1); + if (!name) { + last_error = memory_error; + if (dir) + lt_dlfree(dir); + return 0; + } + /* canonicalize the module name */ + for (i = 0; i < ext - basename; i++) + if (isalnum((int)(basename[i]))) + name[i] = basename[i]; + else + name[i] = '_'; + name[ext - basename] = '\0'; + /* now try to open the .la file */ + file = fopen(filename, LTDL_READTEXT_MODE); + if (!file) + last_error = file_not_found_error; + if (!file && !dir) { + /* try other directories */ + file = (FILE*) find_file(basename, + user_search_path, + &dir, 0); + if (!file) + file = (FILE*) find_file(basename, + getenv("LTDL_LIBRARY_PATH"), + &dir, 0); +#ifdef LTDL_SHLIBPATH_VAR + if (!file) + file = (FILE*) find_file(basename, + getenv(LTDL_SHLIBPATH_VAR), + &dir, 0); +#endif + } + if (!file) { + if (name) + lt_dlfree(name); + if (dir) + lt_dlfree(dir); + return 0; + } + line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX); + if (!line) { + fclose(file); + last_error = memory_error; + return 0; + } + /* read the .la file */ + while (!feof(file)) { + if (!fgets(line, LTDL_FILENAME_MAX, file)) + break; + if (line[0] == '\n' || line[0] == '#') + continue; +# undef STR_DLNAME +# define STR_DLNAME "dlname=" + if (strncmp(line, STR_DLNAME, + sizeof(STR_DLNAME) - 1) == 0) + error = trim(&dlname, + &line[sizeof(STR_DLNAME) - 1]); + else +# undef STR_OLD_LIBRARY +# define STR_OLD_LIBRARY "old_library=" + if (strncmp(line, STR_OLD_LIBRARY, + sizeof(STR_OLD_LIBRARY) - 1) == 0) + error = trim(&old_name, + &line[sizeof(STR_OLD_LIBRARY) - 1]); + else +# undef STR_LIBDIR +# define STR_LIBDIR "libdir=" + if (strncmp(line, STR_LIBDIR, + sizeof(STR_LIBDIR) - 1) == 0) + error = trim(&libdir, + &line[sizeof(STR_LIBDIR) - 1]); + else +# undef STR_DL_DEPLIBS +# define STR_DL_DEPLIBS "dl_dependency_libs=" + if (strncmp(line, STR_DL_DEPLIBS, + sizeof(STR_DL_DEPLIBS) - 1) == 0) + error = trim(&deplibs, + &line[sizeof(STR_DL_DEPLIBS) - 1]); + else + if (strcmp(line, "installed=yes\n") == 0) + installed = 1; + else + if (strcmp(line, "installed=no\n") == 0) + installed = 0; + if (error) + break; + } + fclose(file); + lt_dlfree(line); + /* allocate the handle */ + handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t)); + if (!handle || error) { + if (handle) + lt_dlfree(handle); + if (!error) + last_error = memory_error; + free_vars(name, dir, dlname, old_name, libdir, deplibs); + return 0; + } + handle->usage = 0; + if (load_deplibs(handle, deplibs) == 0) { + newhandle = handle; + /* find_module may replace newhandle */ + if (find_module(&newhandle, dir, libdir, + dlname, old_name, installed)) { + unload_deplibs(handle); + error = 1; + } + } else + error = 1; + if (error) { + lt_dlfree(handle); + free_vars(name, dir, dlname, old_name, libdir, deplibs); + return 0; + } + if (handle != newhandle) { + unload_deplibs(handle); + } + } else { + /* not a libtool module */ + handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t)); + if (!handle) { + last_error = memory_error; + if (dir) + lt_dlfree(dir); + return 0; + } + handle->usage = 0; + /* non-libtool modules don't have dependencies */ + handle->depcount = 0; + handle->deplibs = 0; + newhandle = handle; + if (tryall_dlopen(&newhandle, filename) + && (!dir + || (!find_file(basename, user_search_path, + 0, &newhandle) + && !find_file(basename, + getenv("LTDL_LIBRARY_PATH"), + 0, &newhandle) +#ifdef LTDL_SHLIBPATH_VAR + && !find_file(basename, + getenv(LTDL_SHLIBPATH_VAR), + 0, &newhandle) +#endif + ))) { + lt_dlfree(handle); + if (dir) + lt_dlfree(dir); + return 0; + } + } +register_handle: + if (newhandle != handle) { + lt_dlfree(handle); + handle = newhandle; + } + if (!handle->usage) { + handle->usage = 1; + handle->name = name; + handle->next = handles; + handles = handle; + } else if (name) + lt_dlfree(name); + if (dir) + lt_dlfree(dir); + last_error = saved_error; + return handle; +} + +lt_dlhandle +lt_dlopenext (filename) + const char *filename; +{ + lt_dlhandle handle; + char *tmp; + int len; + const char *saved_error = last_error; + + if (!filename) + return lt_dlopen(filename); + len = strlen(filename); + if (!len) { + last_error = file_not_found_error; + return 0; + } + /* try the normal file name */ + handle = lt_dlopen(filename); + if (handle) + return handle; + /* try "filename.la" */ + tmp = (char*) lt_dlmalloc(len+4); + if (!tmp) { + last_error = memory_error; + return 0; + } + strcpy(tmp, filename); + strcat(tmp, ".la"); + handle = lt_dlopen(tmp); + if (handle) { + last_error = saved_error; + lt_dlfree(tmp); + return handle; + } +#ifdef LTDL_SHLIB_EXT + /* try "filename.EXT" */ + if (strlen(shlib_ext) > 3) { + lt_dlfree(tmp); + tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1); + if (!tmp) { + last_error = memory_error; + return 0; + } + strcpy(tmp, filename); + } else + tmp[len] = '\0'; + strcat(tmp, shlib_ext); + handle = lt_dlopen(tmp); + if (handle) { + last_error = saved_error; + lt_dlfree(tmp); + return handle; + } +#endif + last_error = file_not_found_error; + lt_dlfree(tmp); + return 0; +} + +int +lt_dlclose (handle) + lt_dlhandle handle; +{ + lt_dlhandle cur, last; + + /* check whether the handle is valid */ + last = cur = handles; + while (cur && handle != cur) { + last = cur; + cur = cur->next; + } + if (!cur) { + last_error = invalid_handle_error; + return 1; + } + handle->usage--; + if (!handle->usage) { + int error; + + if (handle != handles) + last->next = handle->next; + else + handles = handle->next; + error = handle->type->lib_close(handle); + error += unload_deplibs(handle); + if (handle->filename) + lt_dlfree(handle->filename); + if (handle->name) + lt_dlfree(handle->name); + lt_dlfree(handle); + return error; + } + return 0; +} + +lt_ptr_t +lt_dlsym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + int lensym; + char lsym[LTDL_SYMBOL_LENGTH]; + char *sym; + lt_ptr_t address; + + if (!handle) { + last_error = invalid_handle_error; + return 0; + } + if (!symbol) { + last_error = symbol_error; + return 0; + } + lensym = strlen(symbol); + if (handle->type->sym_prefix) + lensym += strlen(handle->type->sym_prefix); + if (handle->name) + lensym += strlen(handle->name); + if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH) + sym = lsym; + else + sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1); + if (!sym) { + last_error = buffer_overflow_error; + return 0; + } + if (handle->name) { + /* this is a libtool module */ + if (handle->type->sym_prefix) { + strcpy(sym, handle->type->sym_prefix); + strcat(sym, handle->name); + } else + strcpy(sym, handle->name); + strcat(sym, "_LTX_"); + strcat(sym, symbol); + /* try "modulename_LTX_symbol" */ + address = handle->type->find_sym(handle, sym); + if (address) { + if (sym != lsym) + lt_dlfree(sym); + return address; + } + } + /* otherwise try "symbol" */ + if (handle->type->sym_prefix) { + strcpy(sym, handle->type->sym_prefix); + strcat(sym, symbol); + } else + strcpy(sym, symbol); + address = handle->type->find_sym(handle, sym); + if (sym != lsym) + lt_dlfree(sym); + return address; +} + +const char * +lt_dlerror LTDL_PARAMS((void)) +{ + const char *error = last_error; + + last_error = 0; + return error; +} + +int +lt_dladdsearchdir (search_dir) + const char *search_dir; +{ + if (!search_dir || !strlen(search_dir)) + return 0; + if (!user_search_path) { + user_search_path = strdup(search_dir); + if (!user_search_path) { + last_error = memory_error; + return 1; + } + } else { + char *new_search_path = (char*) + lt_dlmalloc(strlen(user_search_path) + + strlen(search_dir) + 2); /* ':' + '\0' == 2 */ + if (!new_search_path) { + last_error = memory_error; + return 1; + } + strcpy(new_search_path, user_search_path); + strcat(new_search_path, ":"); + strcat(new_search_path, search_dir); + lt_dlfree(user_search_path); + user_search_path = new_search_path; + } + return 0; +} + +int +lt_dlsetsearchpath (search_path) + const char *search_path; +{ + if (user_search_path) + lt_dlfree(user_search_path); + user_search_path = 0; /* reset the search path */ + if (!search_path || !strlen(search_path)) + return 0; + user_search_path = strdup(search_path); + if (!user_search_path) + return 1; + return 0; +} + +const char * +lt_dlgetsearchpath LTDL_PARAMS((void)) +{ + return user_search_path; +} diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h new file mode 100644 index 00000000..bebbc6d2 --- /dev/null +++ b/libltdl/ltdl.h @@ -0,0 +1,91 @@ +/* ltdl.h -- generic dlopen functions + Copyright (C) 1998-1999 Free Software Foundation, Inc. + Originally by Thomas Tanner <tanner@gmx.de> + This file is part of GNU Libtool. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Library General Public License, +if you distribute this file as part of a program that uses GNU libtool +to create libraries and programs, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Only include this header file once. */ +#ifndef _LTDL_H_ +#define _LTDL_H_ 1 + +/* __BEGIN_DECLS should be used at the beginning of your declarations, + so that C++ compilers don't mangle their names. Use __END_DECLS at + the end of C declarations. */ +#undef __BEGIN_DECLS +#undef __END_DECLS +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS /* empty */ +# define __END_DECLS /* empty */ +#endif + +/* LTDL_PARAMS is a macro used to wrap function prototypes, so that compilers + that don't understand ANSI C prototypes still work, and ANSI C + compilers can issue warnings about type mismatches. */ +#undef LTDL_PARAMS +#undef lt_ptr_t +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) +# define LTDL_PARAMS(protos) protos +# define lt_ptr_t void* +#else +# define LTDL_PARAMS(protos) () +# define lt_ptr_t char* +#endif + +#include <stdlib.h> + +#ifdef _LTDL_COMPILE_ +typedef struct lt_dlhandle_t *lt_dlhandle; +#else +typedef lt_ptr_t lt_dlhandle; +#endif + +typedef struct { + const char *name; + lt_ptr_t address; +} lt_dlsymlist; + +__BEGIN_DECLS +extern int lt_dlinit LTDL_PARAMS((void)); +extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded)); +extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded)); +extern int lt_dlexit LTDL_PARAMS((void)); +extern lt_dlhandle lt_dlopen LTDL_PARAMS((const char *filename)); +extern lt_dlhandle lt_dlopenext LTDL_PARAMS((const char *filename)); +extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle)); +extern lt_ptr_t lt_dlsym LTDL_PARAMS((lt_dlhandle handle, const char *name)); +extern const char *lt_dlerror LTDL_PARAMS((void)); +extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir)); +extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path)); +extern const char *lt_dlgetsearchpath LTDL_PARAMS((void)); + +extern const lt_dlsymlist lt_preloaded_symbols[]; +#define LTDL_SET_PRELOADED_SYMBOLS() lt_dlpreload_default(lt_preloaded_symbols) + +extern lt_ptr_t (*lt_dlmalloc)LTDL_PARAMS((size_t size)); +extern void (*lt_dlfree)LTDL_PARAMS((lt_ptr_t ptr)); + +__END_DECLS + +#endif /* !_LTDL_H_ */ diff --git a/libltdl/stamp-h.in b/libltdl/stamp-h.in new file mode 100644 index 00000000..9788f702 --- /dev/null +++ b/libltdl/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/ltconfig b/ltconfig new file mode 100755 index 00000000..2347e694 --- /dev/null +++ b/ltconfig @@ -0,0 +1,1512 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# A lot of this script is taken from autoconf-2.10. + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +echo=echo +if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : +else + # The Solaris and AIX default echo program unquotes backslashes. + # This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # So, we emulate echo with printf '%s\n' + echo="printf %s\\n" + if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : + else + # Oops. We have no working printf. Try to find a not-so-buggy echo. + echo=echo + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH /usr/ucb; do + if test -f $dir/echo && test "X`$dir/echo '\t'`" = 'X\t'; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.2 +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking. +enable_static=yes +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +verify_host=yes +with_gcc=no +with_gnu_ld=no + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_NM="$NM" +old_RANLIB="$RANLIB" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <<EOM +Usage: $progname [OPTION]... LTMAIN [HOST] + +Generate a system-specific libtool script. + + --disable-shared do not build shared libraries + --disable-static do not build static libraries + --help display this help and exit + --no-verify do not verify that HOST is a valid host type + --quiet same as \`--silent' + --silent do not print informational messages + --srcdir=DIR find \`config.guess' in DIR + --version output version information and exit + --with-gcc assume that the GNU C compiler will be used + --with-gnu-ld assume that the C compiler uses the GNU linker + +LTMAIN is the \`ltmain.sh' shell script fragment that provides basic libtool +functionality. + +HOST is the canonical host system name [default=guessed]. +EOM + exit 0 + ;; + + --disable-shared) enable_shared=no ;; + + --disable-static) enable_static=no ;; + + --quiet | --silent) silent=yes ;; + + --srcdir) prev=srcdir ;; + --srcdir=*) srcdir="$optarg" ;; + + --no-verify) verify_host=no ;; + + --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION"; exit 0 ;; + + --with-gcc) with_gcc=yes ;; + --with-gnu-ld) with_gnu_ld=yes ;; + + -*) + echo "$progname: unrecognized option \`$option'" 1>&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test -f "$ltmain"; then : +else + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to ltmain.sh. + srcdir=`$echo "$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds;\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib;$old_postinstall_cmds" +fi + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + IFS="$save_ifs" + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:424: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF + if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:432: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + no_builtin_flag=' -fno-builtin' + + case "$host_os" in + aix3* | aix4* | irix5* | irix6* | osf3* | osf4*) + # PIC is the default for these OSes. + ;; + os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4.2uw2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:547: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:548: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:591: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftestdata + if ln -s X conftestdata 2>/dev/null; then + $rm conftestdata + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:624: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:642: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:645: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +archive_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= + +case "$host_os" in +amigaos* | sunos4*) + # On these operating systems, we should treat GNU ld like the system ld. + gnu_ld_acts_native=yes + ;; +*) + gnu_ld_acts_native=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes && test "$gnu_ld_acts_native" != yes; then + + # See if GNU ld supports shared libraries. + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs' + runpath_var=LD_RUN_PATH + ld_shlibs=yes + else + ld_shlibs=no + fi + + if test "$ld_shlibs" = yes; then + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$LD -o $objdir/$soname$libobjs -bE:$lib.exp -T512 -H512 -bM:SRE;$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$CC -o $objdir/$soname$libobjs ${wl}-bE:$lib.exp ${wl}-bM:SRE ${wl}-bnoentry;$AR cru $lib $objdir/$soname' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data;$echo "#define NAME $libname" > $objdir/a2ixlibrary.data;$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data;$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data;$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data;$AR cru $lib$libobjs;$RANLIB $lib;(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3, at last, uses gcc -shared to do shared libraries. + freebsd3*) + archive_cmds='$CC -shared -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + archive_cmds='$rm $objdir/$soname;$LD -b +s +b $install_libdir -o $objdir/$soname$libobjs;mv $objdir/$soname $lib' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + archive_cmds='$LD -b +h $soname +s +b $install_libdir -o $lib$libobjs' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + archive_cmds='$LD -shared -o $lib -soname $soname -set_version $verstring$libobjs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + ;; + + netbsd*) + # Tested with NetBSD 1.2 ld + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def;$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def;$echo DATA >> $objdir/$libname.def;$echo " SINGLE NONSHARED" >> $objdir/$libname.def;$echo EXPORTS >> $objdir/$libname.def;emxexp$libobjs >> $objdir/$libname.def;$CC -Zdll -Zcrtdll -o $lib$libobjs $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3* | osf4*) + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} -o $lib -soname $soname -set_version $verstring$libobjs$deplibs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -o $lib$libobjs' + hardcode_direct=yes + ;; + + solaris2*) + no_undefined_flag=' -z text' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + + # Solaris 2 before 2.5 hardcodes -L paths. + case "$host_os" in + solaris2.[0-4]*) + hardcode_minus_L=yes + ;; + esac + ;; + + sunos4*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared -o $lib$libobjs' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib$libobjs' + fi + + if test "$with_gnu_ld" = yes; then + export_dynamic_flag_spec='${wl}-export-dynamic' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + can_build_shared=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + /* | [A-Za-z]:\\*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + else + NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRSTU]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \1' + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDTU]' + ;; +irix*) + # Cannot use undefined symbols on IRIX because inlined functions mess us up. + symcode='[BCDEGRST]' + ;; +solaris2*) + symcode='[BDTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTUW]' +fi + +# Write the raw and C identifiers. +global_symbol_pipe="sed -n -e 's/^.* $symcode $sympat$/$symxfrm/p'" + +# Check to see that the pipe works correctly. +pipe_works=no +$rm conftest* +cat > conftest.c <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +main(){nm_test_var='a';nm_test_func();return(0);} +EOF + +echo "$progname:971: checking if global_symbol_pipe works" >&5 +if { (eval echo $progname:972: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:975: eval \"$NM conftest.o | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.o | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`$echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + rm -f "$nlist"T + count=-1 + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + sed 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> conftest.c + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{ +EOF + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.o conftestm.o + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS='conftestm.o' + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi +else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* + +# Do not use the global_symbol_pipe unless it works. +echo "$ac_t$pipe_works" 1>&6 +test "$pipe_works" = yes || global_symbol_pipe= + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && \ + test "$hardcode_minus_L" != no && \ + test "$hardcode_shlibpath_var" != no; then + + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +elif test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" != yes; then + # We cannot hardcode anything. + hardcode_action=unsupported +else + # We can only hardcode existing directories. + hardcode_action=relink +fi +echo "$ac_t$hardcode_action" 1>&6 +test "$hardcode_action" = unsupported && can_build_shared=no + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linker may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +version_type=none +dynamic_linker="$host_os ld.so" + +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3* | aix4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so.$major' + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +freebsd2* | freebsd3*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +gnu*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + shlibpath_var=SHLIB_PATH + library_names_spec='${libname}${release}.sl.$versuffix ${libname}${release}.sl.$major $libname.sl' + soname_spec='${libname}${release}.sl.$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + finish_cmds='PATH="$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd* | openbsd*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4.2uw2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds;\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" + +# Now quote all the things that may contain metacharacters. +for var in ltecho old_CC old_CFLAGS old_CPPFLAGS old_LD old_NM old_RANLIB \ + old_LN_S AR CC LD LN_S NM reload_flag reload_cmds wl pic_flag \ + link_static_flag no_builtin_flag export_dynamic_flag_spec \ + libname_spec library_names_spec soname_spec RANLIB \ + old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds postinstall_cmds postuninstall_cmds \ + allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe \ + hardcode_libdir_flag_spec hardcode_libdir_separator; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | archive_cmds | \ + postinstall_cmds | postuninstall_cmds | finish_cmds) + # Double-quote double-evaled strings. + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\"\`" + ;; + *) + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`" + ;; + esac +done + +ofile=libtool +trap "$rm $ofile; exit 1" 1 2 15 +echo creating $ofile +$rm $ofile +cat <<EOF > $ofile +#! /bin/sh + +# libtool - Provide generalized library-building support services. +# Generated automatically by $PROGRAM - GNU $PACKAGE $VERSION +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 program was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC="$old_CC" CFLAGS="$old_CFLAGS" CPPFLAGS="$old_CPPFLAGS" \\ +# LD="$old_LD" NM="$old_NM" RANLIB="$old_RANLIB" LN_S="$old_LN_S" \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +# An echo program that does not interpret backslashes. +echo="$ltecho" + +# The version of $progname that generated this script. +LTCONFIG_VERSION="$VERSION" + +# Shell to use when invoking shell scripts. +SHELL=${CONFIG_SHELL-/bin/sh} + +# Whether or not to build libtool libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build old-style libraries. +build_old_libs=$enable_static + +# The host system. +host_alias="$host_alias" +host="$host" + +# The archiver. +AR="$AR" + +# The default C compiler. +CC="$CC" + +# The linker used to build libraries. +LD="$LD" + +# Whether we need hard or soft links. +LN_S="$LN_S" + +# A BSD-compatible nm program. +NM="$NM" + +# The name of the directory that contains temporary libtool files. +objdir="$objdir" + +# How to create reloadable object files. +reload_flag="$reload_flag" +reload_cmds="$reload_cmds" + +# How to pass a linker flag through the compiler. +wl="$wl" + +# Additional compiler flags for building library objects. +pic_flag="$pic_flag" + +# Compiler flag to prevent dynamic linking. +link_static_flag="$link_static_flag" + +# Compiler flag to turn off builtin functions. +no_builtin_flag="$no_builtin_flag" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="$export_dynamic_flag_spec" + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec="$libname_spec" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="$library_names_spec" + +# The coded name of the library, if different from the real name. +soname_spec="$soname_spec" + +# Commands used to build and install an old-style archive. +RANLIB="$RANLIB" +old_archive_cmds="$old_archive_cmds" +old_postinstall_cmds="$old_postinstall_cmds" +old_postuninstall_cmds="$old_postuninstall_cmds" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="$old_archive_from_new_cmds" + +# Commands used to build and install a shared archive. +archive_cmds="$archive_cmds" +postinstall_cmds="$postinstall_cmds" +postuninstall_cmds="$postuninstall_cmds" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="$allow_undefined_flag" + +# Flag that forces no undefined symbols. +no_undefined_flag="$no_undefined_flag" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="$finish_cmds" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="$finish_eval" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="$global_symbol_pipe" + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +EOF + +case "$host_os" in +aix3*) + cat <<\EOF >> $ofile +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES +fi + +EOF + ;; +esac + +# Append the ltmain.sh script. +cat "$ltmain" >> $ofile || (rm -f $ofile; exit 1) + +chmod +x $ofile +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/ltmain.sh b/ltmain.sh new file mode 100644 index 00000000..e9350b3f --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,2453 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +# The name of this program. +progname=`$echo "$0" | sed 's%^.*/%%'` +modename="$progname" + +# Constants. +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.2 + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if test "$LTCONFIG_VERSION" != "$VERSION"; then + echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION" + exit 0 + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + $echo "$modename: you cannot specify the output filename with \`-o'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + + # Recognize several different file suffixes. + xform='[cCFSfms]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e 's/\.lo$/.o/'` ;; + *) + $echo "$modename: cannot determine name of library object from \`$srcfile'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + $run $rm $obj $libobj + trap "$run $rm $obj $libobj; exit 1" 1 2 15 + else + $run $rm $libobj + trap "$run $rm $libobj; exit 1" 1 2 15 + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + $show "$base_compile$pic_flag -DPIC $srcfile" + if $run eval "$base_compile\$pic_flag -DPIC \$srcfile"; then : + else + test -n "$obj" && $run $rm $obj + exit 1 + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag"; then + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj + exit $? + fi + + # Just move the object, then go on to compile the next one + $show "$mv $obj $libobj" + $run $mv $obj $libobj || exit 1 + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + # Suppress compiler output if we already did a PIC compilation. + $show "$base_compile $srcfile$suppress_output" + if $run eval "$base_compile \$srcfile$suppress_output"; then : + else + $run $rm $obj $libobj + exit 1 + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + CC="$nonopt" + allow_undefined=yes + compile_command="$CC" + finalize_command="$CC" + + compile_shlibpath= + finalize_shlibpath= + deplibs= + dlfiles= + dlprefiles= + export_dynamic=no + hardcode_libdirs= + libobjs= + link_against_libtool_libs= + ltlibs= + objs= + prev= + prevarg= + release= + rpath= + perm_rpath= + temp_rpath= + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case "$arg" in + -all-static | -static) + if test "X$arg" = "X-all-static" && test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + for arg + do + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + *) + dlprefiles="$dlprefiles $arg" + test "$prev" = dlfiles && dlfiles="$dlfiles $arg" + prev= + ;; + esac + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath) + rpath="$rpath $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + if test "$export_dynamic" != yes; then + export_dynamic=yes + if test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + else + arg= + fi + + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + fi + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's%^-L\(.*\)$%\1%'` + case "$dir" in + /* | [A-Za-z]:\\*) + # Add the corresponding hardcode_libdir_flag, if it is not identical. + ;; + *) + $echo "$modename: \`-L$dir' cannot specify a relative directory" 1>&2 + exit 1 + ;; + esac + deplibs="$deplibs $arg" + ;; + + -l*) deplibs="$deplibs $arg" ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.a) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e 's/\.lo$/\.o/'` + prev= + fi + libobjs="$libobjs $arg" + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$libdir"; then + $echo "$modename: \`$arg' contains no -rpath information" 1>&2 + exit 1 + fi + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname"; then + # If there is no dlname, we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test "$build_libtool_libs" = yes && test -n "$library_names"; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # This is the magic to use -rpath. + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + # Do the same for the permanent run path. + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + + + case "$hardcode_action" in + immediate) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = no; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + relink) + # We need an absolute path. + case "$dir" in + /* | [A-Za-z]:\\*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + *) + $echo "$modename: \`$hardcode_action' is an unknown hardcode action" 1>&2 + exit 1 + ;; + esac + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + finalize_command="$finalize_command -L$libdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + finalize_shlibpath="$finalize_shlibpath$libdir:" + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + finalize_command="$finalize_command -L$libdir -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + compile_command="$compile_command -L$dir -l$name" + finalize_command="$finalize_command -L$dir -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$vinfo" && test -n "$release"; then + $echo "$modename: you cannot specify both \`-version-info' and \`-release'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + oldlib= + oldobjs= + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + */* | *\\*) + $echo "$modename: output file \`$output' must have no directory components" 1>&2 + exit 1 + ;; + + *.a) + # Now set the variables for building old libraries. + build_libtool_libs=no + build_old_libs=yes + oldlib="$output" + $show "$rm $oldlib" + $run $rm $oldlib + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$output" in + lib*) ;; + *) + $echo "$modename: libtool library \`$arg' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + name=`$echo "X$output" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + current=0 + revision=0 + age=0 + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: libtool library \`$output' may not depend on uninstalled libraries:$link_against_libtool_libs" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating libtool libraries" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$rpath"; then + $echo "$modename: you must specify an installation directory with \`-rpath'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo + IFS="$save_ifs" + + if test -n "$5"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + test -n "$2" && current="$2" + test -n "$3" && revision="$3" + test -n "$4" && age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + version_vars="version_type current age revision" + case "$version_type" in + none) ;; + + linux) + version_vars="$version_vars major versuffix" + major=`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + version_vars="$version_vars versuffix verstring" + major=`expr $current - $age` + versuffix="$current.$age.$revision" + verstring="$versuffix" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + version_vars="$version_vars major versuffix" + major="$current" + versuffix="$current.$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Create the output directory, or remove our outputs if we need to. + if test -d $objdir; then + $show "$rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.*" + $run $rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.* + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + # Add libc to deplibs on all systems. + dependency_libs="$deplibs" + deplibs="$deplibs -lc" + + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are PIC. + test -z "$pic_flag" && libobjs=`$echo "X$libobjs " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//g'` + + # Do each of the archive commands. + eval cmds=\"$archive_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + $show "(cd $objdir && $LN_S $realname $linkname)" + $run eval '(cd $objdir && $LN_S $realname $linkname)' || exit $? + done + + # If -export-dynamic was specified, set the dlname. + if test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + + # Now set the variables for building old libraries. + oldlib="$objdir/$libname.a" + ;; + + *.lo | *.o) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into reloadable objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored while creating objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating objects" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored while creating objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while creating objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e 's/\.lo$/.o/'` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Create the old-style object. + reload_objs="$objs"`$echo "X$libobjs " | $Xsed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'` + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + test -z "$libobj" && exit 0 + + if test "$build_libtool_libs" != yes; then + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj || exit 1 + fi + + exit 0 + ;; + + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while linking programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + if test -n "$rpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + fi + + # Substitute the hardcoded libdirs into the compile commands. + if test -n "$hardcode_libdir_separator"; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + finalize_command=`$echo "X$finalize_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + fi + + if test "$export_dynamic" = yes && test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${output}S.c" + else + dlsyms= + fi + + if test -n "$dlsyms"; then + # Add our own program objects to the preloaded list. + dlprefiles=`$echo "X$objs$dlprefiles " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + + # Discover the nlist of each of the dlfiles. + nlist="$objdir/${output}.nm" + + if test -d $objdir; then + $show "$rm $nlist ${nlist}T" + $run $rm "$nlist" "${nlist}T" + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + # Parse the name list into a source file. + $show "creating $objdir/$dlsyms" + if test -z "$run"; then + # Make sure we at least have an empty file. + test -f "$nlist" || : > "$nlist" + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + $rm "$nlist"T + count=-1 + fi + + case "$dlsyms" in + "") ;; + *.c) + $echo > "$objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$output' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define dld_preloaded_symbol_count some_other_symbol +#define dld_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test -f "$nlist"; then + sed -e 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> "$objdir/$dlsyms" + else + echo '/* NONE */' >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + +#undef dld_preloaded_symbol_count +#undef dld_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{\ +" + + if test -f "$nlist"; then + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif\ +" + ;; + + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + fi + + # Now compile the dynamic symbol file. + $show "(cd $objdir && $CC -c$no_builtin_flag \"$dlsyms\")" + $run eval '(cd $objdir && $CC -c$no_builtin_flag "$dlsyms")' || exit $? + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + elif test "$export_dynamic" != yes; then + test -n "$dlfiles$dlprefiles" && $echo "$modename: warning: \`-dlopen' and \`-dlpreopen' are ignored without \`-export-dynamic'" 1>&2 + else + # We keep going just in case the user didn't refer to + # dld_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + + # We have no uninstalled library dependencies, so finalize right now. + $show "$compile_command" + $run eval "$compile_command" + exit $? + fi + + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'T%g'` + + # Create the binary in the object directory, then wrap it. + if test -d $objdir; then : + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + /* | [A-Za-z]:\\*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + # Delete the old output file. + $run $rm $output + + if test -n "$compile_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_command="$runpath_var=\"$rpath\$$runpath_var\" $compile_command" + finalize_command="$runpath_var=\"$rpath\$$runpath_var\" $finalize_command" + fi + + case "$hardcode_action" in + relink) + # AGH! Flame the AIX and HP-UX people for me, will ya? + $echo "$modename: warning: using a buggy system linker" 1>&2 + $echo "$modename: relinking will be required before \`$output' can be installed" 1>&2 + ;; + esac + + $show "$compile_command" + $run eval "$compile_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the finalize command for shipping. + finalize_command=`$echo "X$finalize_command" | $Xsed -e "$sed_quote_subst"` + + # Quote $echo for shipping. + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! /bin/sh + +# $output - temporary wrapper script for $objdir/$output +# Generated by ltmain.sh - GNU $PACKAGE $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of \``pwd`'. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + link_against_libtool_libs='$link_against_libtool_libs' + finalize_command=\"$finalize_command\" +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" = \"$magic\"; then : + else + echo=\"$qecho\" + file=\"\$0\" + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + /* | [A-Za-z]:\\*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" + + progdir=\"\$thisdir/$objdir\" + program='$output' + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/:*\$//'\` + + export $shlibpath_var +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} + + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + if test "$build_old_libs" = "yes"; then + # Transform .lo files to .o files. + oldobjs="$objs"`$echo "X$libobjs " | $Xsed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'` + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.a" + + $show "creating $output" + + # Only create the output if not a dry run. + if test -z "$run"; then + $echo > $output "\ +# $output - a libtool library file +# Generated by ltmain.sh - GNU $PACKAGE $VERSION + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $objdir && $LN_S ../$output $output)" + $run eval "(cd $objdir && $LN_S ../$output $output)" || exit 1 + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional /bin/sh argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL"; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir= + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test -n "$isdir"; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + /* | [A-Za-z]:\\*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + test "X$dlname" = "X$realname" && dlname= + + if test $# -gt 0; then + # Delete the old symlinks. + rmcmd="$rm" + for linkname + do + rmcmd="$rmcmd $destdir/$linkname" + done + $show "$rmcmd" + $run $rmcmd + + # ... and create new ones. + for linkname + do + test "X$dlname" = "X$linkname" && dlname= + $show "(cd $destdir && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $LN_S $realname $linkname)" + done + fi + + if test -n "$dlname"; then + # Install the dynamically-loadable library. + $show "$install_prog $dir/$dlname $destdir/$dlname" + $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $? + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + $show "$install_prog $file $destdir/$name" + $run eval "$install_prog $file $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e 's/\.lo$/\.o/'` + ;; + *.o) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e 's/\.lo$/\.o/'` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + link_against_libtool_libs= + finalize_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs" || test -z "$finalize_command"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -z "$libdir"; then + $echo "$modename: warning: \`$lib' contains no -rpath information" 1>&2 + elif test -f "$libfile"; then : + else + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + if test "$hardcode_action" = relink; then + if test "$finalize" = yes; then + $echo "$modename: warning: relinking \`$file' on behalf of your buggy system linker" 1>&2 + $show "$finalize_command" + if $run eval "$finalize_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + continue + fi + file="$objdir/$file"T + else + $echo "$modename: warning: cannot relink \`$file' on behalf of your buggy system linker" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $dest" + $run eval "$install_prog\$stripme \$file \$dest" || exit $? + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" + fi + done + fi + + echo "------------------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "To link against installed libraries in a given directory, LIBDIR," + echo "you must use the \`-LLIBDIR' flag during linking." + echo + echo " You will also need to do one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "------------------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test -f "$file"; then : + else + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + test "X$n" = "X$dlname" && dlname= + done + test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname" + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e 's/\.lo$/\.o/'` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + +-n, --dry-run display commands without modifying any files + --features display configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to dld_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only +library objects (\`.lo' files) may be specified, and \`-rpath' is required. + +If OUTPUT-FILE ends in \`.a', then a standard library is created using \`ar' +and \`ranlib'. + +If OUTPUT-FILE ends in \`.lo' or \`.o', then a reloadable object file is +created, otherwise an executable program is created." + ;; + +uninstall) + $echo +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/missing b/missing new file mode 100755 index 00000000..e4b838ca --- /dev/null +++ b/missing @@ -0,0 +1,134 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996. + +# 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. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison touch file \`y.tab.c' + makeinfo touch the output file + yacc touch file \`y.tab.c'" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. It should be needed only if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. It should be needed only if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. It should be needed only if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + touch config.h.in + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. It should be needed only if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print \ + | sed 's/^\(.*\).am$/touch \1.in/' \ + | sh + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. It should be needed only if + your modified any \`.y' file. For being effective, your + modifications might require the \`Bison' package. Grab it from + any GNU archive site." + touch y.tab.c + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. It should be needed only if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 00000000..91f6d04e --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,32 @@ +#!/bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Last modified: 1994-03-25 +# Public domain + +errstatus=0 + +for file in ${1+"$@"} ; do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d in ${1+"$@"} ; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/modules/Makefile.am b/modules/Makefile.am new file mode 100644 index 00000000..01ef5c23 --- /dev/null +++ b/modules/Makefile.am @@ -0,0 +1,9 @@ +noinst_PROGRAMS = test.so time.so + +test_so_SOURCES = test.c +time_so_SOURCES = time.c + +EXTRA_DIST = test.m4 time.m4 + +INCLUDES = -I$(srcdir)/../src -I$(srcdir)/../lib +LDFLAGS = -shared diff --git a/modules/Makefile.in b/modules/Makefile.in new file mode 100644 index 00000000..06248f02 --- /dev/null +++ b/modules/Makefile.in @@ -0,0 +1,300 @@ +# Makefile.in generated automatically by automake 1.3b from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 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. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +PACKAGE = @PACKAGE@ +PERL = @PERL@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +STACKOVF = @STACKOVF@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +l = @l@ + +noinst_PROGRAMS = test.so time.so + +test_so_SOURCES = test.c +time_so_SOURCES = time.c + +EXTRA_DIST = test.m4 time.m4 + +INCLUDES = -I$(srcdir)/../src -I$(srcdir)/../lib +LDFLAGS = -shared +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(noinst_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LIBS = @LIBS@ +test_so_OBJECTS = test.o +test_so_LDADD = $(LDADD) +test_so_DEPENDENCIES = +test_so_LDFLAGS = +time_so_OBJECTS = time.o +time_so_LDADD = $(LDADD) +time_so_DEPENDENCIES = +time_so_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = README Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +DEP_FILES = .deps/test.P .deps/time.P +SOURCES = $(test_so_SOURCES) $(time_so_SOURCES) +OBJECTS = $(test_so_OBJECTS) $(time_so_OBJECTS) + +all: Makefile $(PROGRAMS) + +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstPROGRAMS: + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +distclean-noinstPROGRAMS: + +maintainer-clean-noinstPROGRAMS: + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +test.so: $(test_so_OBJECTS) $(test_so_DEPENDENCIES) + @rm -f test.so + $(LINK) $(test_so_LDFLAGS) $(test_so_OBJECTS) $(test_so_LDADD) $(LIBS) + +time.so: $(time_so_OBJECTS) $(time_so_DEPENDENCIES) + @rm -f time.so + $(LINK) $(time_so_LDFLAGS) $(time_so_OBJECTS) $(time_so_LDADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = modules + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu modules/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + +maintainer-clean-depend: + -rm -rf .deps + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $< + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $< + @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \ + < .deps/$(*F).p > .deps/$(*F).P + @-rm -f .deps/$(*F).p +info: +dvi: +check: all +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean: mostlyclean-noinstPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +clean: clean-noinstPROGRAMS clean-compile clean-tags clean-depend \ + clean-generic mostlyclean + +distclean: distclean-noinstPROGRAMS distclean-compile distclean-tags \ + distclean-depend distclean-generic clean + -rm -f config.status + +maintainer-clean: maintainer-clean-noinstPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \ +clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info dvi \ +installcheck install-exec install-data install uninstall all \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# 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/modules/README b/modules/README new file mode 100644 index 00000000..93e7bbb1 --- /dev/null +++ b/modules/README @@ -0,0 +1,62 @@ +This directory contains demonstration modules for GNU m4. + +Nothing in this directory is built by default. + +Dynamic modules is a experimental feature of GNU m4, and might change or +disappear altogether in future versions. Currently it has only been +certified to work under Linux 2.0. + +Dynamic modules are only available if GNU m4 was configured with +--with-modules and if the dlopen(3) interface is available in the +operating system. + +Implementation details are in ../src/module.c + +A module is a compiled shared object, i.e., modules are written in C and +then compiled. The compiled file can then be loaded into a running m4 +process by calling the builtin "loadmodule". This will give GNU m4 +access to any system feature with a C interface. + +A module extends GNU m4 by defining new builtins, It can define builtins +with the same names as existing builtins, which will then be +unavailable. A module cannot redefine internal functions of GNU m4, +such as the input parser or argument handling. + +The infrastructure for writing and compiling modules is still a bit +wanting, quasi non-existent. + +Each module should include the two header files ../src/m4.h and +../src/builtin.h. These will include <ctype.h>, <stdio.h>, +../lib/obstack.h and ../config.h. + +Each module *must* define the symbol "m4_macro_table" as a pointer to a +table of "struct builtin" (defined in m4.h). The table ends with an +entry with name == NULL. The builtins described in the table will be +defined by GNU m4 as were they normal builtins. + +If a module defines the symbol "m4_init_module", it is supposed to be a +function with a prototype of "void m4_init_module(struct obstack *obs)", +and it will be called as soon as the module is loaded. Any non-finished +object left on the obstack will be the expansion of the call of the +builtin "loadmodule". The obstack pointer might be NULL (in the future). + +If a module defines the symbol "m4_finish_module", it is supposed to be +a function with a prototype of "void m4_finish_module(void)", and it +will be called just before GNU m4 exits. This will allow a module to +clean up before exit. There is no way of communicating information to +the user, as GNU m4 exits immeidately afterwards. + +No other symbols will be used by GNU m4. Other external symbols within +the module are private and will not be accessible to GNU m4 or to other +modules. + +Modules are allowed to call external functions already defined within +the GNU m4 sources. Some of these have prototypes in builtin.h. + + +A complete, though silly, example is found in test.c. A more +interesting example is in time.c. + +To try the demos, compile with `make' and run them with the commands as: + + M4MODPATH=`pwd` ../src/m4 time.m4 diff --git a/modules/TODO b/modules/TODO new file mode 100644 index 00000000..c5d7ec4d --- /dev/null +++ b/modules/TODO @@ -0,0 +1,3 @@ +The file src/m4.h will have to be split to have an installable m4defs.h +suitable for modules. Modules should be compilable without have the m4 +source available. diff --git a/modules/defs b/modules/defs new file mode 100644 index 00000000..403eabbe --- /dev/null +++ b/modules/defs @@ -0,0 +1,58 @@ +# -*- ksh -*- +# Defines for GNU m4 testing environment. +# Erick Branderhorst <Erick.Branderhorst@asml.nl> + +# Ensure $srcdir set correctly. +test -f ${srcdir}/defs || { + echo "defs: installation error" 1>&2 + exit 1 +} + +# If srcdir is relative, we need to modify it. +case "$srcdir" in + /*) + ;; + + .) + srcdir=".." + ;; + + *) + srcdir="../$srcdir" + ;; +esac + +rm -rf testSubDir > /dev/null 2>&1 +mkdir testSubDir +cd testSubDir + +# Build appropriate environment in test directory. Eg create +# configure.in, touch all necessary files, etc. + +# nothing yet + +# See how redirections should work. User can set VERBOSE to see all +# output. +test -z "$VERBOSE" && { + exec > /dev/null 2>&1 +} + +# User can set MAKE to choose which make to use. Must use GNU make. +test -z "$MAKE" && MAKE=make + +echo "=== Running test $0" + +# See how GNU m4 should be run. No options as default. +test -z "$M4" && M4="${SHELL-/bin/sh} ../../libtool --mode=execute ../../src/m4" + +# See how cmp should be run. +test -z "$CMP" && CMP=cmp + +# Setting nls related vars. Override them in the test when needed. +LANGUAGE=C +export LANGUAGE +LC_ALL=C +export LC_ALL +LANG=C +export LANG + diff --git a/modules/modpath1.test b/modules/modpath1.test new file mode 100755 index 00000000..2722ed43 --- /dev/null +++ b/modules/modpath1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# test.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +# cannot perform test without --with-modules +#test -z "$WITH_MODULES" && exit 77 + +cat ${srcdir}/test.m4 >in + +cat <<'EOF' >ok +Test module loaded. +Test module called. +Dumpdef: +EOF + +cat <<'EOF' >okerr +test: <test> +EOF + + +M4PATH=$srcdir:$srcdir/../tests $M4 -M `cd $srcdir; pwd` -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/modpath2.test b/modules/modpath2.test new file mode 100755 index 00000000..06af519a --- /dev/null +++ b/modules/modpath2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# test.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +# cannot perform test without --with-modules +#test -z "$WITH_MODULES" && exit 77 + +cat ${srcdir}/test.m4 >in + +cat <<'EOF' >ok +Test module loaded. +Test module called. +Dumpdef: +EOF + +cat <<'EOF' >okerr +test: <test> +EOF + +LTDL_LIBRARY_PATH=`cd $srcdir; pwd` M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/modpath3.test b/modules/modpath3.test new file mode 100755 index 00000000..6064265b --- /dev/null +++ b/modules/modpath3.test @@ -0,0 +1,30 @@ +#!/bin/sh + +# test.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +# cannot perform test without --with-modules +#test -z "$WITH_MODULES" && exit 77 + + + +cat <<'EOF' >in +test +Dumpdef: dumpdef(`test') +EOF + +cat <<'EOF' >ok +Test module called. +Dumpdef: +EOF + +cat <<'EOF' >okerr +test: <test> +EOF + + +M4PATH=$srcdir:$srcdir/../tests $M4 -m test -M `cd $srcdir; pwd` -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/modpath4.test b/modules/modpath4.test new file mode 100755 index 00000000..780cdbeb --- /dev/null +++ b/modules/modpath4.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# test.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +cat ${srcdir}/test.m4 >in + + +cat <<'EOF' >ok +Test module loaded. +Test module called. +Dumpdef: +EOF + +cat <<'EOF' >okerr +test: <test> +EOF + + +M4MODPATH=`cd $srcdir; pwd` M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/shadow.c b/modules/shadow.c new file mode 100644 index 00000000..5955828b --- /dev/null +++ b/modules/shadow.c @@ -0,0 +1,75 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <m4module.h> /* This is obligatory */ + +#define LTDL_MODULE_NAME shadow + +module_init_t m4_init_module; /* initialisation function */ +module_finish_t m4_finish_module; /* cleanup function */ + +/* declare builtins */ +M4BUILTIN(shadow); +M4BUILTIN(test); +#undef M4BUILTIN + +#define m4_macro_table shadow_LTX_m4_macro_table +#define m4_init_module shadow_LTX_m4_init_module +#define m4_finish_module shadow_LTX_m4_finish_module + +/* The table of builtins defined by this module - just one */ + +builtin m4_macro_table[] = +{ + /* name GNUext macros blind function */ + { "shadow", FALSE, FALSE, FALSE, shadow }, + { "test", FALSE, FALSE, FALSE, test }, + { 0, FALSE, FALSE, FALSE, 0 }, +}; + +void +m4_init_module(struct obstack *obs) +{ + char *s = "Shadow module loaded."; + if (obs != 0) + obstack_grow (obs, s, strlen(s)); +} + +void +m4_finish_module(void) +{ + return; +} + +/* The functions for builtins can be static */ +static void +shadow (struct obstack *obs, int argc, token_data **argv) +{ + char *s = "Shadow::`shadow' called."; + obstack_grow (obs, s, strlen(s)); +} + +static void +test (struct obstack *obs, int argc, token_data **argv) +{ + char *s = "Shadow::`test' called."; + obstack_grow (obs, s, strlen(s)); +} + + + diff --git a/modules/shadow.m4 b/modules/shadow.m4 new file mode 100644 index 00000000..b55adbcb --- /dev/null +++ b/modules/shadow.m4 @@ -0,0 +1,59 @@ +# no modules loaded yet +test +shadow + +# define our own macros for `test' and `shadow' +define(`test', `local::`test'') +define(`shadow', `local::`shadow'') +test +shadow + +# save our local `shadow' macro until the Shadow module is unloaded +pushdef(`shadow') + +# module Shadow defines `shadow' and `test' macros +loadmodule(`shadow') +dumpdef(`test') +dumpdef(`shadow') +test +shadow + +# save the definition of `test' from the Shadow module +define(`Shadow::test', defn(`test')) + +# module Test also defines a `test' macro +loadmodule(`test') +dumpdef(`test') +dumpdef(`shadow') +test +shadow + +# Reloading Shadow shouldn't affect anything +loadmodule(`shadow') +dumpdef(`test') +dumpdef(`shadow') +test +shadow + +# Unloading Test will not unshadow the test definition in Shadow without +# some macro magic +unloadmodule(`test') +define(`test', defn(`Shadow::test')) +undefine(`Shadow::test') +dumpdef(`test') +dumpdef(`shadow') +test +shadow + +# Unloading Shadow once has no effect (we loaded it twice) +unloadmodule(`shadow') +dumpdef(`test') +dumpdef(`shadow') +test +shadow + +# Unloading Shadow again will revert to copying `test' and the locally +# pushed `shadow' macro. +unloadmodule(`shadow') +test +shadow diff --git a/modules/shadow.test b/modules/shadow.test new file mode 100755 index 00000000..c8952b59 --- /dev/null +++ b/modules/shadow.test @@ -0,0 +1,91 @@ +#!/bin/sh + +# shadow.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +# cannot perform test without --with-modules +# test -z "$WITH_MODULES" && exit 77 + +cat ${srcdir}/shadow.m4 >in + +cat <<'EOF' >ok +# no modules loaded yet +test +shadow + +# define our own macros for `test' and `shadow' + + +local::test +local::shadow + +# save our local `shadow' macro until the Shadow module is unloaded + + +# module Shadow defines `shadow' and `test' macros +Shadow module loaded. + + +Shadow::test called. +Shadow::shadow called. + +# save the definition of `test' from the Shadow module + + +# module Test also defines a `test' macro +Test module loaded. + + +Test module called. +Shadow::shadow called. + +# Reloading Shadow shouldn't affect anything + + + +Test module called. +Shadow::shadow called. + +# Unloading Test will not unshadow the test definition in Shadow without +# some macro magic + + + + + +Shadow::test called. +Shadow::shadow called. + +# Unloading Shadow once has no effect (we loaded it twice) + + + +Shadow::test called. +Shadow::shadow called. + +# Unloading Shadow again will revert to copying `test' and the locally +# pushed `shadow' macro. + +test +local::shadow +EOF + +cat <<'EOF' >okerr +test: <test> +shadow: <shadow> +test: <test> +shadow: <shadow> +test: <test> +shadow: <shadow> +test: <test> +shadow: <shadow> +test: <test> +shadow: <shadow> +EOF + + +M4PATH=$srcdir:$srcdir/../tests $M4 -M `cd $srcdir; pwd` -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/stdlib.c b/modules/stdlib.c new file mode 100644 index 00000000..6ba8556d --- /dev/null +++ b/modules/stdlib.c @@ -0,0 +1,293 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <m4.h> +#include <builtin.h> + +#include <pwd.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/utsname.h> +#include <sys/types.h> + +DECLARE(m4_getcwd); +DECLARE(m4_getlogin); +DECLARE(m4_getpid); +DECLARE(m4_getppid); +DECLARE(m4_getuid); +DECLARE(m4_getpwnam); +DECLARE(m4_getpwuid); +DECLARE(m4_hostname); +DECLARE(m4_rand); +DECLARE(m4_srand); +DECLARE(m4_getenv); +DECLARE(m4_setenv); +DECLARE(m4_unsetenv); +DECLARE(m4_uname); + +#undef DECLARE + +builtin m4_macro_table[] = +{ + /* name GNUext macros blind function */ + { "getcwd", TRUE, FALSE, FALSE, m4_getcwd }, + { "getenv", TRUE, FALSE, TRUE, m4_getenv }, + { "setenv", TRUE, FALSE, TRUE, m4_setenv }, + { "unsetenv", TRUE, FALSE, TRUE, m4_unsetenv }, + { "getlogin", TRUE, FALSE, FALSE, m4_getlogin }, + { "getpid", TRUE, FALSE, FALSE, m4_getpid }, + { "getppid", TRUE, FALSE, FALSE, m4_getppid }, + { "getpwnam", TRUE, FALSE, TRUE, m4_getpwnam }, + { "getpwuid", TRUE, FALSE, TRUE, m4_getpwuid }, + { "getuid", TRUE, FALSE, FALSE, m4_getuid }, + { "hostname", TRUE, FALSE, FALSE, m4_hostname }, + { "rand", TRUE, FALSE, FALSE, m4_rand }, + { "srand", TRUE, FALSE, FALSE, m4_srand }, + { "uname", TRUE, FALSE, FALSE, m4_uname }, + { 0, FALSE, FALSE, FALSE, 0 }, +}; + + + +static void +m4_getcwd (struct obstack *obs, int argc, token_data **argv) +{ + char buf[1024]; + char *bp; + int l; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + bp = getcwd(buf, sizeof buf); + + if (bp != NULL) /* in case of error return null string */ + shipout_string (obs, buf, 0 , FALSE); +} + +static void +m4_getenv (struct obstack *obs, int argc, token_data **argv) +{ + char *env; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + env = getenv(ARG(1)); + + if (env != NULL) + shipout_string (obs, env, 0, FALSE); +} + +static void +m4_setenv (struct obstack *obs, int argc, token_data **argv) +{ + char *env; + int overwrite = 1; + + if (bad_argc (argv[0], argc, 3, 4)) + return; + + if (argc == 4) + if (!numeric_arg(argv[0], ARG(3), &overwrite)) + return; + + setenv(ARG(1), ARG(2), overwrite); +} + +static void +m4_unsetenv (struct obstack *obs, int argc, token_data **argv) +{ + char *env; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + unsetenv(ARG(1)); +} + +static void +m4_getlogin (struct obstack *obs, int argc, token_data **argv) +{ + char *login; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + login = getlogin(); + + if (login != NULL) + shipout_string (obs, login, 0, FALSE); +} + +static void +m4_getpid (struct obstack *obs, int argc, token_data **argv) +{ + if (bad_argc (argv[0], argc, 1, 1)) + return; + + shipout_int(obs, getpid()); +} + +static void +m4_getppid (struct obstack *obs, int argc, token_data **argv) +{ + if (bad_argc (argv[0], argc, 1, 1)) + return; + + shipout_int(obs, getppid()); +} + +static void +m4_getpwnam (struct obstack *obs, int argc, token_data **argv) +{ + struct passwd *pw; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + pw = getpwnam(ARG(1)); + + if (pw != NULL) + { + shipout_string (obs, pw->pw_name, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_passwd, 0, TRUE); + obstack_1grow (obs, ','); + shipout_int(obs, pw->pw_uid); + obstack_1grow (obs, ','); + shipout_int(obs, pw->pw_gid); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_gecos, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_dir, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_shell, 0, TRUE); + } +} + +static void +m4_getpwuid (struct obstack *obs, int argc, token_data **argv) +{ + struct passwd *pw; + int uid; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + if (!numeric_arg(argv[0], ARG(1), &uid)) + return; + + pw = getpwuid(uid); + + if (pw != NULL) + { + shipout_string (obs, pw->pw_name, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_passwd, 0, TRUE); + obstack_1grow (obs, ','); + shipout_int(obs, pw->pw_uid); + obstack_1grow (obs, ','); + shipout_int(obs, pw->pw_gid); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_gecos, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_dir, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, pw->pw_shell, 0, TRUE); + } +} + +static void +m4_hostname (struct obstack *obs, int argc, token_data **argv) +{ + char buf[1024]; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + if (gethostname(buf, sizeof buf) < 0) + return; + + shipout_string (obs, buf, 0, FALSE); +} + +static void +m4_rand (struct obstack *obs, int argc, token_data **argv) +{ + int i; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + shipout_int(obs, rand()); +} + +static void +m4_srand (struct obstack *obs, int argc, token_data **argv) +{ + char buf[64]; + int seed; + + if (bad_argc (argv[0], argc, 1, 2)) + return; + + if (argc == 1) + seed = time(0L) * getpid(); + else + { + if (!numeric_arg(argv[0], ARG(1), &seed)) + return; + } + + srand(seed); +} + +static void +m4_uname (struct obstack *obs, int argc, token_data **argv) +{ + struct utsname ut; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + if (uname(&ut) == 0) + { + shipout_string (obs, ut.sysname, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, ut.nodename, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, ut.release, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, ut.machine, 0, TRUE); + obstack_1grow (obs, ','); + shipout_string (obs, ut.domainname, 0, TRUE); + } +} + +static void +m4_getuid (struct obstack *obs, int argc, token_data **argv) +{ + int i; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + shipout_int(obs, getuid()); +} diff --git a/modules/stdlib.m4 b/modules/stdlib.m4 new file mode 100644 index 00000000..a023643d --- /dev/null +++ b/modules/stdlib.m4 @@ -0,0 +1,41 @@ +loadmodule(`stdlib') + +`getenv - 'getenv(PATH) + +setenv TEST=??? setenv(`TEST', `???') +getenv TEST - getenv(`TEST') + +setenv TEST=Second test setenv(`TEST', `Second test') +getenv TEST - getenv(`TEST') + +unsetenv TEST unsetenv(`TEST') +getenv TEST - getenv(`TEST') + + + +`getlogin - 'getlogin +`getcwd = 'getcwd +`getpid - 'getpid +`getppid - 'getppid + +syscmd(`ps ajx|grep m4') + +`getuid - 'getuid + +user root - getpwnam(`root') +user sync - getpwnam(`sync') +user rene - getpwnam(`rene') + +uid 5 - getpwuid(5) +me - getpwuid(getuid) + +`hostname = 'hostname + +`rand' - rand,rand,rand,rand +`srand' srand +`rand' - rand,rand,rand,rand +`srand' srand +`rand' - rand,rand,rand,rand + +`uname - ' uname + diff --git a/modules/test.c b/modules/test.c new file mode 100644 index 00000000..1a8a8092 --- /dev/null +++ b/modules/test.c @@ -0,0 +1,58 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <m4.h> /* These are obligatory */ +#include <builtin.h> + +module_init_t m4_init_module; /* initialisation function */ +module_finish_t m4_finish_module; /* cleanup function */ + +DECLARE(test); /* declare test as implementing + a builtin */ + +#undef DECLARE + +/* The table of builtins defined by this module - just one */ + +builtin m4_macro_table[] = +{ + /* name GNUext macros blind function */ + { "test", FALSE, FALSE, FALSE, test }, + { 0, FALSE, FALSE, FALSE, 0 }, +}; + +void +m4_init_module(struct obstack *obs) +{ + char *s = "Test module loaded."; + obstack_grow (obs, s, strlen(s)); +} + +void +m4_finish_module(void) +{ + return; +} + +/* The functions for builtins can be static */ +static void +test (struct obstack *obs, int argc, token_data **argv) +{ + char *s = "Test module called"; + obstack_grow (obs, s, strlen(s)); +} diff --git a/modules/test.m4 b/modules/test.m4 new file mode 100644 index 00000000..f8486578 --- /dev/null +++ b/modules/test.m4 @@ -0,0 +1,3 @@ +loadmodule(`test.so') +test +Dumpdef: dumpdef(`test') diff --git a/modules/test.test b/modules/test.test new file mode 100755 index 00000000..6f0c335f --- /dev/null +++ b/modules/test.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# test.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +cat ${srcdir}/test.m4 >in + + +cat <<'EOF' >ok +Test module loaded. +Test module called. +Dumpdef: +EOF + +cat <<'EOF' >okerr +test: <test> +EOF + + +M4PATH=$srcdir:$srcdir/../tests $M4 -M `cd $srcdir; pwd` -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/time.c b/modules/time.c new file mode 100644 index 00000000..5f98e8a7 --- /dev/null +++ b/modules/time.c @@ -0,0 +1,193 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <m4.h> +#include <builtin.h> + +#include <time.h> + +DECLARE(m4_currenttime); +DECLARE(m4_ctime); +DECLARE(m4_gmtime); +DECLARE(m4_localtime); +DECLARE(m4_mktime); +DECLARE(m4_strftime); + +#undef DECLARE + +builtin m4_macro_table[] = +{ + /* name GNUext macros blind function */ + { "currenttime", TRUE, FALSE, FALSE, m4_currenttime }, + { "ctime", TRUE, FALSE, FALSE, m4_ctime }, + { "gmtime", TRUE, FALSE, TRUE, m4_gmtime }, + { "localtime", TRUE, FALSE, TRUE, m4_localtime }, + { "mktime", TRUE, FALSE, TRUE, m4_mktime }, + { "strftime", TRUE, FALSE, TRUE, m4_strftime }, + { 0, FALSE, FALSE, FALSE, 0 }, +}; + + + +static void +m4_currenttime (struct obstack *obs, int argc, token_data **argv) +{ + char buf[64]; + time_t now; + int l; + + if (bad_argc (argv[0], argc, 1, 1)) + return; + + now = time(0L); + l = sprintf(buf, "%ld", now); + + obstack_grow (obs, buf, l); +} + +static void +m4_ctime (struct obstack *obs, int argc, token_data **argv) +{ + char buf[64]; + time_t t; + int l; + + if (bad_argc (argv[0], argc, 1, 2)) + return; + + if (argc == 2) + numeric_arg(argv[0], ARG(1), (int *)&t); + else + t = time(0L); + + obstack_grow (obs, ctime(&t), 24); +} + +static void +format_tm(struct obstack *obs, struct tm *tm) +{ + shipout_int(obs, tm->tm_sec); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_min); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_hour); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_mday); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_mon); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_year); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_wday); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_yday); + obstack_1grow(obs, ','); + + shipout_int(obs, tm->tm_isdst); +} + +static void +m4_gmtime (struct obstack *obs, int argc, token_data **argv) +{ + time_t t; + struct tm *tm; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + if (!numeric_arg (argv[0], ARG (1), (int *)&t)) + return; + + format_tm(obs, gmtime(&t)); +} + +static void +m4_localtime (struct obstack *obs, int argc, token_data **argv) +{ + time_t t; + struct tm *tm; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + if (!numeric_arg (argv[0], ARG (1), (int *)&t)) + return; + + format_tm(obs, localtime(&t)); +} + +/*-------------------------------------------. +| mktime(sec,min,hour,mday,month,year,isdst) | +`-------------------------------------------*/ + +static void +m4_mktime (struct obstack *obs, int argc, token_data **argv) +{ + struct tm tm; + time_t t; + + if (bad_argc (argv[0], argc, 7, 8)) + return; + + if (!numeric_arg (argv[0], ARG (1), &tm.tm_sec)) + return; + if (!numeric_arg (argv[0], ARG (2), &tm.tm_min)) + return; + if (!numeric_arg (argv[0], ARG (3), &tm.tm_hour)) + return; + if (!numeric_arg (argv[0], ARG (4), &tm.tm_mday)) + return; + if (!numeric_arg (argv[0], ARG (5), &tm.tm_mon)) + return; + if (!numeric_arg (argv[0], ARG (6), &tm.tm_year)) + return; + if (ARG(7) && !numeric_arg (argv[0], ARG (7), &tm.tm_isdst)) + return; + + t = mktime(&tm); + + shipout_int(obs, t); +} + +static void +m4_strftime (struct obstack *obs, int argc, token_data **argv) +{ + struct tm *tm; + time_t t; + char *buf; + int l; + + if (bad_argc (argv[0], argc, 3, 3)) + return; + + if (!numeric_arg (argv[0], ARG (2), (int *)&t)) + return; + + tm = localtime(&t); + + buf = (char *) obstack_alloc(obs, 1024); + l = strftime(buf, 1024, ARG(1), tm); + obstack_grow(obs, buf, l); +} diff --git a/modules/time.m4 b/modules/time.m4 new file mode 100644 index 00000000..e87f6bdf --- /dev/null +++ b/modules/time.m4 @@ -0,0 +1,16 @@ +loadmodule(`time.so') + +`currenttime' = currenttime +`ctime' = ctime != ctime(eval(currenttime+60*60*24)) +gmtime = gmtime(currenttime) +localtime = localtime(currenttime) +define(`q', `$1,$2,$3,$4,$5,$6,$9')dnl + +currenttime +eval(currenttime+60*60*24) +localtime(eval(currenttime+60*60*24)) +q(localtime(eval(currenttime+60*60*24))) +mktime = mktime(q(localtime(eval(currenttime+60*60*24)))) + +%A %B %d, %Y = strftime(`%A %B %d, %Y', currenttime) +%X on %x = strftime(`%X on %x', currenttime) diff --git a/modules/time.test b/modules/time.test new file mode 100755 index 00000000..a2155e69 --- /dev/null +++ b/modules/time.test @@ -0,0 +1,50 @@ +#!/bin/sh + +# test.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ../../tests/config.sh + +cat <<'EOF' >in +ifelse(regexp(currenttime, `^[1-9][0-9]*$'), 0, NUMERIC, NON NUMERIC) + +define(`sometime', 1890962700)dnl someones 65th birthday, hopefully +`ctime' = ctime(sometime) != ctime(eval(sometime+60*60*24)) +gmtime = gmtime(sometime) +localtime = localtime(sometime) +define(`q', `$1,$2,$3,$4,$5,$6,$9')dnl + +sometime +eval(sometime+60*60*24) +localtime(eval(sometime+60*60*24)) +q(localtime(eval(sometime+60*60*24))) +mktime = mktime(q(localtime(eval(sometime+60*60*24)))) + +%A %B %d, %Y = strftime(`%A %B %d, %Y', sometime) +%X on %x = strftime(`%X on %x', sometime) +EOF + +cat <<'EOF' >ok +NUMERIC + +ctime = Mon Dec 3 04:25:00 2029 != Tue Dec 4 04:25:00 2029 +gmtime = 0,25,3,3,11,129,1,336,0 +localtime = 0,25,4,3,11,129,1,336,0 + +1890962700 +1891049100 +0,25,4,4,11,129,2,337,0 +0,25,4,4,11,129,0 +mktime = 1891049100 + +%A %B %d, %Y = Monday December 03, 2029 +%X on %x = 04:25:00 on 12/03/29 +EOF + +cat <<'EOF' >okerr +EOF + + +M4PATH=$srcdir:$srcdir/../tests $M4 -m time -M `cd $srcdir; pwd` -d in >out 2>err +sed -e "s,^[^:]*[lt-]*m4[.ex]*:,m4:," err >sederr && mv sederr err +$CMP -s out ok && $CMP -s err okerr diff --git a/modules/time2.m4 b/modules/time2.m4 new file mode 100644 index 00000000..286f8bfd --- /dev/null +++ b/modules/time2.m4 @@ -0,0 +1,14 @@ +`currenttime' = currenttime +`ctime' = ctime != ctime(eval(currenttime+60*60*24)) +gmtime = gmtime(currenttime) +localtime = localtime(currenttime) +define(`q', `$1,$2,$3,$4,$5,$6,$9')dnl + +currenttime +eval(currenttime+60*60*24) +localtime(eval(currenttime+60*60*24)) +q(localtime(eval(currenttime+60*60*24))) +mktime = mktime(q(localtime(eval(currenttime+60*60*24)))) + +%A %B %d, %Y = strftime(`%A %B %d, %Y', currenttime) +%X on %x = strftime(`%X on %x', currenttime) diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/po/ChangeLog diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 00000000..85b34636 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,254 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996 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. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = $(prefix)/@DATADIRNAME@ +localedir = $(datadir)/locale +gnulocaledir = $(prefix)/share/locale +gettextsrcdir = $(prefix)/share/gettext/po +subdir = po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ + +CC = @CC@ +GENCAT = @GENCAT@ +GMSGFMT = PATH=../src:$$PATH @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = PATH=../src:$$PATH @XGETTEXT@ +MSGMERGE = PATH=../src:$$PATH msgmerge + +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ + +INCLUDES = -I.. -I$(top_srcdir)/intl + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +SOURCES = cat-id-tbl.c +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \ +stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES) + +POTFILES = \ + +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +INSTOBJEXT = @INSTOBJEXT@ + +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat + +.c.o: + $(COMPILE) $< + +.po.pox: + $(MAKE) $(PACKAGE).pot + $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && $(GENCAT) $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: cat-id-tbl.c $(CATALOGS) +all-no: + +$(PACKAGE).pot: $(POTFILES) + $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \ + --add-comments --keyword=_ --keyword=N_ \ + --files-from=$(srcdir)/POTFILES.in + if [ ! -s $(PACKAGE).po ] \ + || cmp -s $(PACKAGE).po $(srcdir)/$(PACKAGE).pot; then \ + rm -f $(PACKAGE).po; \ + else \ + rm -f $(srcdir)/$(PACKAGE).pot \ + && mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot; \ + fi + +cat-id-tbl.c: stamp-cat-id +stamp-cat-id: $(PACKAGE).pot + rm -f cat-id-tbl.tmp + sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \ + | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp + if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \ + rm cat-id-tbl.tmp; \ + else \ + echo cat-id-tbl.c changed; \ + rm -f $(srcdir)/cat-id-tbl.c; \ + mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \ + fi + cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $(datadir); \ + else \ + $(top_srcdir)/mkinstalldirs $(datadir); \ + fi + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + case "$$cat" in \ + *.gmo) destdir=$(gnulocaledir);; \ + *) destdir=$(localedir);; \ + esac; \ + lang=`echo $$cat | sed 's/$(CATOBJEXT)$$//'`; \ + dir=$$destdir/$$lang/LC_MESSAGES; \ + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $$dir; \ + else \ + $(top_srcdir)/mkinstalldirs $$dir; \ + fi; \ + if test -r $$cat; then \ + $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \ + echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \ + fi; \ + if test -r $$cat.m; then \ + $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \ + else \ + if test -r $(srcdir)/$$cat.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$cat.m \ + $$dir/$(PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \ + else \ + true; \ + fi; \ + fi; \ + done + if test "$(PACKAGE)" = "gettext"; then \ + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $(gettextsrcdir); \ + else \ + $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \ + fi; \ + cd $(srcdir) && \ + $(INSTALL_DATA) Makefile.in.in $(gettextsrcdir)/Makefile.in.in; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + lang=`echo $$cat | sed 's/$(CATOBJEXT)$$//'`; \ + rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \ + rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \ + rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \ + rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \ + done + rm -f $(gettextsrcdir)/po-Makefile.in.in + +check: all + +cat-id-tbl.o: ../intl/libgettext.h + +dvi info tags TAGS ID: + +mostlyclean: + rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: update-po $(DISTFILES) + dists="$(DISTFILES)"; \ + for file in $$dists; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(PACKAGE).pot + PATH=`pwd`/../src:$$PATH; \ + cd $(srcdir); \ + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + lang=`echo $$cat | sed 's/$(CATOBJEXT)$$//'`; \ + mv $$lang.po $$lang.old.po; \ + echo "$$lang:"; \ + if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \ + rm -f $$lang.old.po; \ + else \ + echo "msgmerge for $$cat failed!"; \ + rm -f $$lang.po; \ + mv $$lang.old.po $$lang.po; \ + fi; \ + done + +POTFILES: POTFILES.in + ( if test 'x$(srcdir)' != 'x.'; then \ + posrcprefix='$(top_srcdir)/'; \ + else \ + posrcprefix="../"; \ + fi; \ + sed -e '/^#/d' -e '/^[ ]*$$/d' \ + -e "s@.*@ $$posrcprefix& \\\\@" \ + -e '$$s/\(.*\) \\/\1/' < $(srcdir)/POTFILES.in > POTFILES ) + +Makefile: Makefile.in.in ../config.status POTFILES + cd .. \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 00000000..2b770796 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1 @@ +src/m4.c
\ No newline at end of file diff --git a/po/cat-id-tbl.c b/po/cat-id-tbl.c new file mode 100644 index 00000000..45dec044 --- /dev/null +++ b/po/cat-id-tbl.c @@ -0,0 +1,72 @@ +/* Automatically generated by po2tbl.sed from m4.pot. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libgettext.h" + +const struct _msg_ent _msg_tbl[] = { + {"", 1}, + {"ERROR: Stack overflow. (Infinite define recursion?)", 2}, + {"Try `%s --help' for more information.\n", 3}, + {"Usage: %s [OPTION]... [FILE]...\n", 4}, + {"\ +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, --interactive unbuffer output, ignore interrupts\n\ + -E, --fatal-warnings stop execution after first warning\n\ + -Q, --quiet, --silent suppress some warnings for builtins\n\ + -P, --prefix-builtins force a `m4_' prefix to all builtins\n", 5}, + {" -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n", 6}, + {"\ +\n\ +Preprocessor features:\n\ + -I, --include=DIRECTORY search this directory second for includes\n\ + -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n\ + -U, --undefine=NAME delete builtin NAME\n\ + -s, --synclines generate `#line NO \"FILE\"' lines\n", 7}, + {"\ +\n\ +Limits control:\n\ + -G, --traditional suppress all GNU extensions\n\ + -H, --hashsize=PRIME set symbol lookup hash table size\n\ + -L, --nesting-limit=NUMBER change artificial nesting limit\n", 8}, + {"\ +\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", 9}, + {"\ +\n\ +Debugging:\n\ + -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n\ + -t, --trace=NAME trace NAME when it will be defined\n\ + -l, --arglength=NUM restrict macro tracing size\n\ + -o, --error-output=FILE redirect debug and trace output\n", 10}, + {"\ +\n\ +FLAGS is any of:\n\ + t trace for all macro calls, not only traceon'ed\n\ + a show actual arguments\n\ + e show expansion\n\ + q quote values as necessary, with a or e flag\n\ + c show before collect, after collect and after call\n\ + x add a unique macro call id, useful with c flag\n\ + f say current input file name\n\ + l say current input line number\n\ + p show results of path searches\n\ + i show changes in input files\n\ + V shorthand for all of the above flags\n", 11}, + {"\ +\n\ +If no FILE or if FILE is `-', standard input is read.\n", 12}, + {"Bad debug flags: `%s'", 13}, + {"INTERNAL ERROR: Bad code in deferred arguments", 14}, +}; + +int _msg_tbl_length = 14; diff --git a/po/cs.gmo b/po/cs.gmo Binary files differnew file mode 100644 index 00000000..69918181 --- /dev/null +++ b/po/cs.gmo diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 00000000..5e355a64 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,725 @@ +# Czech translation of the GNU m4. +# Copyright (C) 1998 Free Software Foundation, Inc. +# Jiøí Pavlovskư <pavlovsk@ff.cuni.cz>, 1998. +# +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4n\n" +"POT-Creation-Date: 2000-01-10 05:27+0100\n" +"PO-Revision-Date: 1998-12-07 22:02+01:00\n" +"Last-Translator: Jiøí Pavlovskư <pavlovsk@ff.cuni.cz>\n" +"Language-Team: Czech <cs@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/getopt.c:677 +#, c-format +msgid "%s: option `%s' is ambiguous\n" +msgstr "" + +#: lib/getopt.c:702 +#, c-format +msgid "%s: option `--%s' doesn't allow an argument\n" +msgstr "" + +#: lib/getopt.c:707 +#, c-format +msgid "%s: option `%c%s' doesn't allow an argument\n" +msgstr "" + +#: lib/getopt.c:725 lib/getopt.c:898 +#, c-format +msgid "%s: option `%s' requires an argument\n" +msgstr "" + +#. --option +#: lib/getopt.c:754 +#, c-format +msgid "%s: unrecognized option `--%s'\n" +msgstr "" + +#. +option or -option +#: lib/getopt.c:758 +#, c-format +msgid "%s: unrecognized option `%c%s'\n" +msgstr "" + +#. 1003.2 specifies the format of this message. +#: lib/getopt.c:784 +#, c-format +msgid "%s: illegal option -- %c\n" +msgstr "" + +#: lib/getopt.c:787 +#, c-format +msgid "%s: invalid option -- %c\n" +msgstr "" + +#. 1003.2 specifies the format of this message. +#: lib/getopt.c:817 lib/getopt.c:947 +#, c-format +msgid "%s: option requires an argument -- %c\n" +msgstr "" + +#: lib/getopt.c:864 +#, c-format +msgid "%s: option `-W %s' is ambiguous\n" +msgstr "" + +#: lib/getopt.c:882 +#, c-format +msgid "%s: option `-W %s' doesn't allow an argument\n" +msgstr "" + +#: lib/obstack.c:471 +msgid "memory exhausted" +msgstr "" + +#: lib/regex.c:1019 +msgid "Success" +msgstr "" + +#: lib/regex.c:1022 +msgid "No match" +msgstr "" + +# , c-format +#: lib/regex.c:1025 +#, fuzzy +msgid "Invalid regular expression" +msgstr "©patnư regulární vưraz `%s': %s" + +#: lib/regex.c:1028 +msgid "Invalid collation character" +msgstr "" + +#: lib/regex.c:1031 +msgid "Invalid character class name" +msgstr "" + +#: lib/regex.c:1034 +msgid "Trailing backslash" +msgstr "" + +#: lib/regex.c:1037 +msgid "Invalid back reference" +msgstr "" + +#: lib/regex.c:1040 +msgid "Unmatched [ or [^" +msgstr "" + +#: lib/regex.c:1043 +msgid "Unmatched ( or \\(" +msgstr "" + +#: lib/regex.c:1046 +msgid "Unmatched \\{" +msgstr "" + +#: lib/regex.c:1049 +msgid "Invalid content of \\{\\}" +msgstr "" + +#: lib/regex.c:1052 +msgid "Invalid range end" +msgstr "" + +#: lib/regex.c:1055 lib/xmalloc.c:82 +msgid "Memory exhausted" +msgstr "" + +# , c-format +#: lib/regex.c:1058 +#, fuzzy +msgid "Invalid preceding regular expression" +msgstr "Chyba pøi porovnávání regulárního vưrazu `%s'" + +#: lib/regex.c:1061 +#, fuzzy +msgid "Premature end of regular expression" +msgstr "Pøedèasnư konec zmrazeného souboru" + +# , c-format +#: lib/regex.c:1064 +#, fuzzy +msgid "Regular expression too big" +msgstr "©patnư regulární vưraz `%s': %s" + +#: lib/regex.c:1067 +msgid "Unmatched ) or \\)" +msgstr "" + +# , c-format +#: lib/regex.c:5564 +#, fuzzy +msgid "No previous regular expression" +msgstr "Chyba pøi porovnávání regulárního vưrazu `%s'" + +# , c-format +#: src/builtin.c:349 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Varování: pøíli¹ málo argumentù pro vestav́né makro `%s'" + +# , c-format +#: src/builtin.c:355 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "" +"Varování: pøíli¹ mnoho argumentù pro vestav́né makro `%s' - budou ignorovány" + +# , c-format +#: src/builtin.c:383 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Neèíselnư argument pro vestav́né makro `%s'" + +#: src/builtin.c:494 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ tokenu v define_macro ()" + +# , c-format +#: src/builtin.c:681 src/builtin.c:780 src/builtin.c:1423 src/builtin.c:1447 +#, c-format +msgid "Undefined name %s" +msgstr "Jméno %s není definováno" + +#: src/builtin.c:721 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "VNITØNÍ CHYBA: Vestav́né makro nenalezeno v tabulce vestav́nưch maker!" + +#: src/builtin.c:729 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ tokenu v m4_dumpdef ()" + +# , c-format +#: src/builtin.c:804 +#, fuzzy, c-format +msgid "Undefined name `%s'" +msgstr "Jméno %s není definováno" + +#: src/builtin.c:842 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ symbolu v m4_defn ()" + +# , c-format +#: src/builtin.c:908 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Rouru do pøíkazu `%s' nelze otevøít" + +# , c-format +#: src/builtin.c:948 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Základ v makru eval je mimo rozsah (základ = %d)" + +#: src/builtin.c:957 +msgid "Negative width to eval" +msgstr "Záporná ¹íøka v makru eval" + +# , c-format +#: src/builtin.c:1063 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "Neèíselnư argument pro %s" + +# , c-format +#: src/builtin.c:1075 +#, c-format +msgid "Cannot undivert %s" +msgstr "Chyba pøi volání makra undivert pro %s" + +# , c-format +#: src/builtin.c:1223 +#, c-format +msgid "Undefined syntax code %c" +msgstr "Syntaktickư kód %c není definován" + +# , c-format +#: src/builtin.c:1274 src/freeze.c:211 +#, c-format +msgid "Cannot open %s" +msgstr "%s nelze otevøít" + +# , c-format +#: src/builtin.c:1483 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Ladící mód: ¹patné ladící volby: `%s'" + +# , c-format +#: src/builtin.c:1519 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Chybovư soubor %s nelze pou¾ít" + +#: src/builtin.c:1740 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "VAROVÁNÍ: \\0 zmizí, pøi nahrazování pou¾ijte \\&" + +# , c-format +#: src/builtin.c:1801 src/builtin.c:1861 src/input.c:1014 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "©patnư regulární vưraz `%s': %s" + +# , c-format +#: src/builtin.c:1812 src/builtin.c:1885 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "Chyba pøi porovnávání regulárního vưrazu `%s'" + +#: src/debug.c:380 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"VNITØNÍ CHYBA: vestav́né makro nenalezeno v tabulce vestav́nưch maker\n" +"(trace_pre ())!" + +#: src/debug.c:388 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "VNITØNÍ CHYBA: ¹patnư typ tokenu (trace_pre ())" + +# , c-format +#: src/eval.c:309 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "©patnư vưraz v makru eval (chybí pravá závorka): %s" + +# , c-format +#: src/eval.c:315 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "©patnư vưraz v makru eval: %s" + +# , c-format +#: src/eval.c:320 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "©patnư vưraz v makru eval (¹patnư vstup): %s" + +# , c-format +#: src/eval.c:325 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "©patnư vưraz v makru eval (nadbyteènư vstup): %s" + +# , c-format +#: src/eval.c:330 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "D́lení nulou v makru eval: %s" + +# , c-format +#: src/eval.c:335 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Modulo nulou v makru eval: %s" + +#: src/eval.c:340 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "VNITØNÍ CHYBA: ¹patnư chybovư kód v evaluate ()" + +#: src/eval.c:594 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "VNITØNÍ CHYBA: ¹patnư operátor porovnání v cmp_term ()" + +#: src/eval.c:639 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "VNITØNÍ CHYBA: ¹patnư operátor posunu v shift_term ()" + +#: src/eval.c:738 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "VNITØNÍ CHYBA: ¹patnư operátor v mult_term ()" + +#: src/freeze.c:119 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "VNITØNÍ CHYBA: Vestav́né makro nenalezeno v tabulce vestav́nưch maker!" + +#: src/freeze.c:132 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ tokenu ve freeze_one_symbol ()" + +#: src/freeze.c:163 +msgid "Expecting line feed in frozen file" +msgstr "Ve zmrazeném souboru oèekáván LF" + +# , c-format +#: src/freeze.c:165 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Ve zmrazeném souboru oèekáván znak `%c'" + +#: src/freeze.c:222 +msgid "Ill-formated frozen file" +msgstr "©patnư formát zmrazeného souboru" + +#: src/freeze.c:277 src/freeze.c:293 +msgid "Premature end of frozen file" +msgstr "Pøedèasnư konec zmrazeného souboru" + +# , c-format +#: src/freeze.c:327 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "`%s' ze zmrazeného souboru nenalezeno v tabulce vestav́nưch maker!" + +# , c-format +#: src/input.c:318 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Vstup èten z %s, øádku %d" + +# , c-format +#: src/input.c:346 +#, c-format +msgid "Input read from %s" +msgstr "Vstup èten z %s" + +#: src/input.c:506 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "VNITØNÍ CHYBA: rekurzivní push_string!" + +#: src/input.c:623 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "VNITØNÍ CHYBA: ¹patné volání init_macro_token ()" + +#: src/input.c:663 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "VNITØNÍ CHYBA: chyba vstupního zásobníku v next_char ()" + +#: src/input.c:700 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "VNITØNÍ CHYBA: chyba vstupního zásobníku v peek_input ()" + +#: src/input.c:805 +msgid "NONE" +msgstr "®ÁDNƯ" + +#: src/input.c:1199 src/input.c:1226 +msgid "ERROR: EOF in string" +msgstr "CHYBA: EOF v øet́zci" + +#: src/m4.c:119 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "CHYBA: Pøeteèení zásobníku. (nekoneèná rekurze makra define?)" + +# , c-format +#: src/m4.c:146 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Více informací získáte pøíkazem `%s --help'.\n" + +# , c-format +#: src/m4.c:150 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "Pou¾ití: %s [PØEPÍNAÈ]... [SOUBOR]...\n" + +#: src/m4.c:151 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Povinné èi volitelné argumenty pro dlouhé pøepínaèe jsou povinné respektive\n" +"volitelné i pro odpovídající pøepínaèe krátké.\n" +"\n" +"Chování programu:\n" +" --help vypí¹e tuto nápov́du a skonèí\n" +" --version vypí¹e oznaèení verze a skonèí\n" +" -e, --interactive nebufferovanư vưstup, ignoruje pøeru¹ení\n" +" -E, --fatal-warnings skonèí po prvním varování\n" +" -Q, --quiet, --silent potlaèí ńkterá varování tưkající se\n" +" vestav́nưch maker\n" +" -P, --prefix-builtins v¹echna vestav́ná makra budou mít prefix " +"`m4_'\n" + +#: src/m4.c:164 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" +" -W, --word-regexp=REGVƯR syntaxe jmen maker bude urèena pomocí REGVƯR\n" + +#: src/m4.c:169 +msgid "" +"\n" +"Dynamic loading features:\n" +" -m, --module-directory=DIRECTORY add DIRECTORY to the module search path\n" +" -M, --load-module=MODULE load dynamic MODULE from M4MODPATH\n" +msgstr "" + +#: src/m4.c:176 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"Nastavení preprocesoru:\n" +" -I, --include=ADRESÁØ ADRESÁØ bude druhư v poøadí pøi hledání\n" +" vlo¾enưch souborù\n" +" -D, --define=MAKRO[=HODNOTA] definuje MAKRO mající HODNOTU, mù¾e bưt\n" +" i prázdné\n" +" -U, --undefine=MAKRO sma¾e vestav́né MAKRO\n" +" -s, --synclines vlo¾í øádky tvaru `#line ÈÍSLO \"SOUBOR\"'\n" + +#: src/m4.c:184 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"Nastavení limitù:\n" +" -G, --traditional vypne roz¹íøení GNU\n" +" -H, --hashsize=PRVOÈÍSLO velikost hash tabulky pro vyhledávání " +"symbolù\n" +" -L, --nesting-limit=ÈÍSLO nastaví limit pro vnoøená volání maker\n" + +#: src/m4.c:191 +msgid "" +"\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" +msgstr "" +"\n" +"Zmrazené soubory:\n" +" -F, --freeze-state=SOUBOR pøi ukonèení ulo¾í zmrazenư stav do SOUBORU\n" +" -R, --reload-state=SOUBOR pøi startu naète zmrazenư stav ze SOUBORU\n" + +#: src/m4.c:197 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Lad́ní:\n" +" -d, --debug=[VOLBY] nastaví úrovẹ lad́ní (pokud nejsou VOLBY\n" +" zadány, pak implicitń `aeq')\n" +" -t, --trace=MAKRO sleduje MAKRO, kdy¾ je definováno\n" +" -l, --arglength=POÈET reguluje poèet vưstupních informací\n" +" ze sledování maker\n" +" -o, --error-output=SOUBOR pøesḿruje vưstup lad́ní a sledování do " +"SOUBORU\n" + +#: src/m4.c:205 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"VOLBOU mù¾e bưt cokoliv z:\n" +" t sleduje v¹echna makra, nejenom ta urèená pomocí traceon\n" +" a vypí¹e aktuální argumenty\n" +" e vypí¹e expanzi\n" +" q dle potøeby uzavøe hodnoty mezi apostrofy, s volbami a nebo e\n" +" c vypí¹e hodnoty pøed a po vyhodnocení argumentù a po volání makra\n" +" x bude vypisovat jedineèné ID volání makra, u¾iteèné s volbou c\n" +" f bude vypisovat jméno vstupního souboru\n" +" l bude vypisovat èíslo vstupního øádku\n" +" p vypí¹e informace o nalezení zadaného souboru\n" +" i vypí¹e informace o ka¾dé zḿń vstupního souboru\n" +" V zkratka pro v¹echny vư¹e uvedené volby\n" + +#: src/m4.c:220 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"Jestli¾e SOUBOR není zadán, nebo je SOUBOR `-', pak je èten standardní " +"vstup.\n" + +#: src/m4.c:225 +msgid "" +"\n" +"Report bugs to <bug-m4@gnu.org>.\n" +msgstr "" +"\n" +"Chyby v programu oznamujte na adrese <bug-m4@gnu.org> (anglicky).\n" +"Pøipomínky k pøekladu zasílejte na adresu <cs@li.org> (èesky).\n" + +# , c-format +#: src/m4.c:414 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "©patné ladící volby: `%s'" + +#: src/m4.c:436 +#, c-format +msgid "ERROR: failed to add search directory `%s'" +msgstr "" + +#: src/m4.c:440 +#, c-format +msgid "ERROR: failed to add search directory `%s': %s" +msgstr "" + +#: src/m4.c:460 +msgid " (options:" +msgstr " (pøelo¾eno s volbami:" + +#: src/m4.c:542 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "VNITØNÍ CHYBA: ¹patnư kód v odlo¾enưch argumentech" + +#: src/macro.c:97 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ tokenu v expand_token ()" + +#: src/macro.c:163 +msgid "ERROR: EOF in argument list" +msgstr "CHYBA: EOF v seznamu argumentù" + +#: src/macro.c:182 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ tokenu v expand_argument ()" + +#: src/macro.c:259 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "VNITØNÍ CHYBA: ¹patnư typ symbolu v call_macro ()" + +# , c-format +#: src/macro.c:288 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "CHYBA: pøekroèen limit pro rekurzi (%d), zṃ́te jej pomocí -L<N>" + +# , c-format +#: src/module.c:123 +#, fuzzy, c-format +msgid "ERROR: failed to initialise modules: %s" +msgstr "CHYBA: modul `%s' nelze nalézt: %s" + +# , c-format +#: src/module.c:221 +#, fuzzy, c-format +msgid "ERROR: cannot find module: `%s'" +msgstr "CHYBA: modul `%s' nelze nalézt" + +# , c-format +#: src/module.c:224 +#, fuzzy, c-format +msgid "ERROR: cannot find module: `%s': %s" +msgstr "CHYBA: modul `%s' nelze nalézt: %s" + +# , c-format +#: src/module.c:274 +#, fuzzy +msgid "ERROR: cannot close modules" +msgstr "CHYBA: modul `%s' nelze nalézt" + +# , c-format +#: src/module.c:277 +#, fuzzy, c-format +msgid "ERROR: cannot cannot close modules: %s" +msgstr "CHYBA: modul `%s' nelze nalézt: %s" + +# , c-format +#: src/module.c:284 +#, fuzzy, c-format +msgid "ERROR: cannot close module: `%s'" +msgstr "CHYBA: modul `%s' nelze nalézt" + +# , c-format +#: src/module.c:288 +#, fuzzy, c-format +msgid "ERROR: cannot cannot close module: `%s': %s" +msgstr "CHYBA: modul `%s' nelze nalézt: %s" + +#: src/output.c:262 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "CHYBA: doèasnư soubor pro ulo¾ení odlo¾eného vưstupu nelze vytvoøit" + +#: src/output.c:272 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "CHYBA: odlo¾enư vưstup nelze zapsat do doèasného souboru" + +#: src/output.c:356 +msgid "ERROR: Copying inserted file" +msgstr "CHYBA: pøi zapisování vlo¾eného souboru" + +#: src/output.c:537 +msgid "ERROR: Reading inserted file" +msgstr "CHYBA: pøi ètení vlo¾eného souboru" + +#: src/output.c:636 +msgid "Cannot stat diversion" +msgstr "Chyba pøi volání funkce stat pro soubor obsahující odlo¾enư vưstup" + +#: src/output.c:639 +msgid "Diversion too large" +msgstr "" + +# , c-format +#: src/path.c:157 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "Hledán soubor `%s', nalezen soubor `%s'" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:175 +msgid "VMEM limit exceeded?\n" +msgstr "Pøekroèen VMEM limit?\n" + +#: src/stackovf.c:197 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Neoprávńnư pøístup do paḿti (SIGSEGV). Jedná se buï o pøeteèení " +"zásobníku,\n" +"nebo o chybu " + +#: src/stackovf.c:202 +msgid ". Check for possible infinite recursion.\n" +msgstr ". Prov́øte, zda se nejedná o nekoneènou rekurzi.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "VNITØNÍ CHYBA: ¹patnư mód pro symbol_lookup ()" + +# , c-format +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Jméno `%s' není známo\n" + +# , c-format +#~ msgid "Undefined macro `%s'" +#~ msgstr "Makro `%s' není definováno" + +# , c-format +#~ msgid "Module search for `%s' found `%s'" +#~ msgstr "Hledán modul `%s', nalezen modul `%s'" diff --git a/po/de.gmo b/po/de.gmo Binary files differnew file mode 100644 index 00000000..d61f7983 --- /dev/null +++ b/po/de.gmo diff --git a/po/de.po b/po/de.po new file mode 100644 index 00000000..f6c51f48 --- /dev/null +++ b/po/de.po @@ -0,0 +1,507 @@ +# German translation for the GNU m4 messages +# Copyright (C) 1995, 1996 Free Software Foundation, Inc. +# Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995 +# Martin von Löwis <martin@mira.isdn.cs.tu-berlin.de>, 1996 +# +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4.3\n" +"POT-Creation-Date: 1998-08-03 17:14+0200\n" +"PO-Revision-Date: 1996-09-30 10:38 GMT+0100\n" +"Last-Translator: Martin von Löwis <martin@mira.isdn.cs.tu-berlin.de>\n" +"Language-Team: German <de@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:272 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Warnung: Zu wenig Argumente für eingebaute Funktion `%s'" + +#: src/builtin.c:278 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "" +"Warnung: Überschüssige Argumente für eingebaute Funktion `%s' ignoriert" + +#: src/builtin.c:298 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Nicht-numerisches Argument in eingebauter Funktion `%s'" + +#: src/builtin.c:438 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "INTERNER FEHLER: Falscher Datentyp des Tokens in define_macro ()" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, c-format +msgid "Undefined name %s" +msgstr "Name %s nicht definiert" + +#: src/builtin.c:636 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "INTERNER FEHLER: Eingebaute Funktion nicht in Tabelle gefunden!" + +#: src/builtin.c:644 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "INTERNER FEHLER: Falscher Datentyp des Tokens in m4_dumpdef ()" + +#: src/builtin.c:695 +#, c-format +msgid "Undefined macro `%s'" +msgstr "Makro `%s' nicht definiert" + +#: src/builtin.c:735 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "INTERNER FEHLER: Falscher Symboltyp in m4_defn ()" + +#: src/builtin.c:772 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Kann keine `pipe' für Kommando `%s' öffnen" + +#: src/builtin.c:811 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Basis in `eval' nicht in den Grenzen (Basis = %d)" + +#: src/builtin.c:820 +msgid "Negative width to eval" +msgstr "Negative Breite in `eval'" + +#: src/builtin.c:925 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "Nicht-numerisches Argument in %s" + +#: src/builtin.c:937 +#, c-format +msgid "Cannot undivert %s" +msgstr "Kann Umleitung %s nicht aufheben" + +#: src/builtin.c:1043 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "Kann %s nicht öffnen" + +#: src/builtin.c:1248 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Debug Modus: falsche Debug Flags: `%s'" + +#: src/builtin.c:1284 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Kann Fehlerdatei nicht vorbereiten: %s" + +#: src/builtin.c:1501 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "WARNUNG: \\0 wird wegfallen, benutze \\& stattdessen" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "Falscher regulärer Ausdruck `%s': %s" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "Fehler beim Erkennen des regulären Ausdrucks `%s'" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"INTERNER FEHLER: Eingebaute Funktion nicht in Tabelle gefunden! (trace_pre " +"())" + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "INTERNER FEHLER: Falscher Datentyp des Tokens (trace_pre ())" + +#: src/eval.c:277 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "Falscher Ausdruck in `eval' (fehlende rechte Klammer): %s" + +#: src/eval.c:283 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "Falscher Ausdruck in `eval': %s" + +#: src/eval.c:288 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "Falscher Ausdruck in `eval' (falsche Eingabe): %s" + +#: src/eval.c:293 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "Falscher Ausdruck in `eval' (zu große Eingabe): %s" + +#: src/eval.c:298 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "Division durch Null in `eval': %s" + +#: src/eval.c:303 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Modulo Null in `eval': %s" + +#: src/eval.c:308 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "INTERNER FEHLER: Falscher Fehlerkode in evaluate ()" + +#: src/eval.c:547 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "INTERNER FEHLER: Falscher Vergleichsoperator in cmp_term ()" + +#: src/eval.c:590 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "INTERNER FEHLER: Falscher Shift-Operator in shift_term ()" + +#: src/eval.c:674 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "INTERNER FEHLER: Falscher Operator in mult_term ()" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "INTERNER FEHLER: Eingebaute Funktion nicht in Tabelle gefunden!" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "INTERNER FEHLER: Falscher Datentyp des Tokens in freeze_one_symbol ()" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "Erwarte Zeilenumbruch in eingefrorener Datei" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Erwarte Zeichen `%c' in eingefrorener Datei" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "Fehlerhafte eingefrorene Datei" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "Vorzeitiges Ende der eingefrorenen Datei" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "" +"`%s' aus eingefrorener Datei nicht in Tabelle der eingebauten Funktionen " +"gefunden!" + +#: src/input.c:174 +#, c-format +msgid "Input read from %s" +msgstr "Eingabe gelesen von %s" + +#: src/input.c:231 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "INTERNER FEHLER: Rekursives push_string!" + +#: src/input.c:311 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Eingabe zurückgenommen zu %s, Zeile %d" + +#: src/input.c:325 +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "" +"INTERNER FEHLER: Kellerspeicher der Eingabe durcheinander in pop_input ()" + +#: src/input.c:364 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "INTERNER FEHLER: Falscher Aufruf von init_macro_token ()" + +#: src/input.c:413 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "" +"INTERNER FEHLER: Kellerspeicher der Eingabe durcheinander in peek_input ()" + +#: src/input.c:470 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "" +"INTERNER FEHLER: Kellerspeicher der Eingabe durcheinander in next_char ()" + +# This is the name of the input file when there is no current input file. +# Is this ever printed in a message? +#: src/input.c:550 +msgid "NONE" +msgstr "NONE" + +#: src/input.c:777 +msgid "ERROR: EOF in string" +msgstr "FEHLER: Dateiende in Zeichenkette" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "FEHLER: Keller voll. (Unendliche `define' Rekursion?)" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "`%s --help' zeigt weitere Informationen.\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "Aufruf: %s [OPTION]... [DATEI]...\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Notwendige bzw. optionale Argumente für Optionen der Langform sind auch \n" +"für die Kurform notwendig bzw. optional.\n" +"\n" +"Operationsmodi:\n" +" --help zeige diese Hilfe an und beende\n" +" --version zeige Versionsinformation an und beende\n" +" -e, --interactive keine Ausgabepufferung, ignoriere Interrupts\n" +" -E, --fatal-warnings beende Ausführung nach erster Warnung\n" +" -Q, --quiet, --silent unterdrücke Warnungen bei eingebauten " +"Funktionen\n" +" -P, --prefix-builtins erzwinge `m4_' Präfix für eingebaute " +"Funktionen\n" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr " -W, --word-regexp=REGEXP benutze REGEXP für Makronamensyntax\n" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"Präprozessoreigenschaften:\n" +" -I, --include=VERZEICHNIS durchsuche VERZEICHNIS als zweites bei " +"`include'\n" +" -D, --define=NAME[=WERT] füge NAME mit WERT (oder leer) ein\n" +" -U, --undefine=NAME lösche eingebaute Funktion NAME\n" +" -s, --synclines erzeuge `#line NR \"DATEI\"' Zeilen\n" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"Setze Grenzen:\n" +" -G, --traditional schalte alle GNU Erweiterungen aus\n" +" -H, --hashsize=PRIMZAHL setze Größe der Symbol-Hashtabelle\n" +" -L, --nesting-limit=NUMMER setze künstliche Grenze für " +"Schachtelungstiefe\n" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" +"\n" +"Eingefrorene Dateien:\n" +" -F, --freeze-state=DATEI erzeuge am Ende eine eingefrorene Form in " +"DATEI\n" +" -R, --reload-state=DATEI lade zu Beginn Zustand von eingefrorener " +"DATEI\n" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] setze Debuglevel (keine FLAGS bedeutet " +"`aeq')\\\n" +" -t, --trace=NAME verfolge NAME, wenn er definiert wird\n" +" -l, --arglength=NUMMER beschränke Größe bei Macroverfolgung\n" +" -o, --error-output=DATEI leite Debug- und Verfolgungsausgaben nach " +"DATEI\n" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"FLAGS ist Kombination aus folgendem:\n" +" t verfolge alle Makroaufrufe, nicht nur die von `traceon'\n" +" a zeige aktuelle Argumente\n" +" e zeige Ausdehnung\n" +" q setze Werte in Anführungszeichen, wenn nötig, mit a- oder e-Flag\n" +" c zeige vor und nach `collect' und nach Aufruf an\n" +" x zeige für jeden Aufruf eindeutige Nummer an, hilfreich bei -c\n" +" f gebe Namen der aktuellen Eingabedatei aus\n" +" l gebe aktuelle Zeilennummer der Eingabezeile aus\n" +" p gebe Ergebnis der Pfadsuche aus\n" +" i gebe Veränderungen der Eingabedatei aus\n" +" V Kurzform für alle Flags oben zusammen\n" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"Ohne DATEI oder wenn DATEI `-' ist, wird die Standardeingabe gelesen\n" + +#: src/m4.c:358 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "Falsche Debug Flags: `%s'" + +#: src/m4.c:437 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "INTERNER FEHLER: Falscher Kode in zurückgestellten Argumenten" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "INTERNER FEHLER: Falscher Datentyp des Tokens in expands_token ()" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "FEHLER: Dateiende in Argumentliste" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "INTERNER FEHLER: Falscher Typ des Tokens in expand_argument ()" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "INTERNER FEHLER: Falsche Symboltyp in call_macro ()" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "" +"FEHLER: Grenze der Rekursion von %d überschritten, benutze -L<N> zur Änderung" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "FEHLER: Kann keine temporäre Datei für Umleitung erzeugen" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "FEHLER: Kann Umleitung nicht in temporäre Datei ausgeben" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "FEHLER: Während Kopieren einer eingefügten Datei" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "FEHLER: Während Lesen einer eingefügten Datei" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "Kann `stat' nicht auf Umleitung anwenden" + +#: src/path.c:131 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "Pfad für Suche nach `%s' hat `%s' gefunden" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "VMEM Beschränkung überschritten?\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Verletzung der Speichergrenzen festgestellt (SIGSEGV). Entweder ist ein\n" +"Stacküberlauf aufgetreten, oder es gibt einen Fehler in " + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". Untersuche auf mögliche unendliche Rekursion.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "INTERNER FEHLER: Illegaler Modus bei symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Name `%s' ist unbekannt\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "Falscher regulärer Ausdruck: `%s': %s" + +#~ msgid "%s: option `%s' is ambiguous\n" +#~ msgstr "%s: Option `%s' ist mehrdeutig\n" + +#~ msgid "%s: option `--%s' doesn't allow an argument\n" +#~ msgstr "%s: Option `--%s' erlaubt kein Argument\n" + +#~ msgid "%s: option `%c%s' doesn't allow an argument\n" +#~ msgstr "%s: Option `%c%s' erlaubt kein Argument\n" + +#~ msgid "%s: option `%s' requires an argument\n" +#~ msgstr "%s: Option `%s' verlangt ein Argument\n" + +#~ msgid "%s: unrecognized option `--%s'\n" +#~ msgstr "%s: nicht erkannte Option `--%s'\n" + +#~ msgid "%s: unrecognized option `%c%s'\n" +#~ msgstr "%s: nicht erkannte Option `%c%s'\n" + +#~ msgid "%s: illegal option -- %c\n" +#~ msgstr "%s: illegale Option -- %c\n" + +#~ msgid "%s: invalid option -- %c\n" +#~ msgstr "%s: ungültige Options -- %c\n" + +#~ msgid "%s: option requires an argument -- %c\n" +#~ msgstr "%s: Option verlangt ein Argument -- %c\n" + +# Der aktuelle Ausdruck ist NULL und vorher gab es auch noch keinen. +#~ msgid "No previous regular expression" +#~ msgstr "Regulärer Ausdruck fehlt" + +#~ msgid "Memory exhausted" +#~ msgstr "Speicher voll" diff --git a/po/el.gmo b/po/el.gmo Binary files differnew file mode 100644 index 00000000..479d0010 --- /dev/null +++ b/po/el.gmo diff --git a/po/el.po b/po/el.po new file mode 100644 index 00000000..4dd6ed1d --- /dev/null +++ b/po/el.po @@ -0,0 +1,690 @@ +# Greek messages for GNU m4. +# Copyright (C) 1999 Free Software Foundation, Inc. +# Simos Xenitellis <S.Xenitellis@rhbnc.ac.uk>, 1999. +# +msgid "" +msgstr "" +"Project-Id-Version: GNU m4 1.4n\n" +"POT-Creation-Date: 2000-01-10 05:27+0100\n" +"PO-Revision-Date: 1999-06-24 00:25+0000\n" +"Last-Translator: Simos Xenitellis <S.Xenitellis@rhbnc.ac.uk>\n" +"Language-Team: Greek <nls@tux.hellug.gr>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-7\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: lib/getopt.c:677 +#, c-format +msgid "%s: option `%s' is ambiguous\n" +msgstr "" + +#: lib/getopt.c:702 +#, c-format +msgid "%s: option `--%s' doesn't allow an argument\n" +msgstr "" + +#: lib/getopt.c:707 +#, c-format +msgid "%s: option `%c%s' doesn't allow an argument\n" +msgstr "" + +#: lib/getopt.c:725 lib/getopt.c:898 +#, c-format +msgid "%s: option `%s' requires an argument\n" +msgstr "" + +#. --option +#: lib/getopt.c:754 +#, c-format +msgid "%s: unrecognized option `--%s'\n" +msgstr "" + +#. +option or -option +#: lib/getopt.c:758 +#, c-format +msgid "%s: unrecognized option `%c%s'\n" +msgstr "" + +#. 1003.2 specifies the format of this message. +#: lib/getopt.c:784 +#, c-format +msgid "%s: illegal option -- %c\n" +msgstr "" + +#: lib/getopt.c:787 +#, c-format +msgid "%s: invalid option -- %c\n" +msgstr "" + +#. 1003.2 specifies the format of this message. +#: lib/getopt.c:817 lib/getopt.c:947 +#, c-format +msgid "%s: option requires an argument -- %c\n" +msgstr "" + +#: lib/getopt.c:864 +#, c-format +msgid "%s: option `-W %s' is ambiguous\n" +msgstr "" + +#: lib/getopt.c:882 +#, c-format +msgid "%s: option `-W %s' doesn't allow an argument\n" +msgstr "" + +#: lib/obstack.c:471 +msgid "memory exhausted" +msgstr "" + +#: lib/regex.c:1019 +msgid "Success" +msgstr "" + +#: lib/regex.c:1022 +msgid "No match" +msgstr "" + +#: lib/regex.c:1025 +#, fuzzy +msgid "Invalid regular expression" +msgstr "ËÜèị̈ êáíïíéễ Ưêöñáóç `%s': %s" + +#: lib/regex.c:1028 +msgid "Invalid collation character" +msgstr "" + +#: lib/regex.c:1031 +msgid "Invalid character class name" +msgstr "" + +#: lib/regex.c:1034 +msgid "Trailing backslash" +msgstr "" + +#: lib/regex.c:1037 +msgid "Invalid back reference" +msgstr "" + +#: lib/regex.c:1040 +msgid "Unmatched [ or [^" +msgstr "" + +#: lib/regex.c:1043 +msgid "Unmatched ( or \\(" +msgstr "" + +#: lib/regex.c:1046 +msgid "Unmatched \\{" +msgstr "" + +#: lib/regex.c:1049 +msgid "Invalid content of \\{\\}" +msgstr "" + +#: lib/regex.c:1052 +msgid "Invalid range end" +msgstr "" + +#: lib/regex.c:1055 lib/xmalloc.c:82 +msgid "Memory exhausted" +msgstr "" + +#: lib/regex.c:1058 +#, fuzzy +msgid "Invalid preceding regular expression" +msgstr "ÓöÜë́á óôï ôáßñéáó́á óôçí êáíïíéễ Ưêöñáóç `%s'" + +#: lib/regex.c:1061 +#, fuzzy +msgid "Premature end of regular expression" +msgstr "Đñüùñï ôƯëị̈ đáăù́Ưíïơ áñ÷åßïơ" + +#: lib/regex.c:1064 +#, fuzzy +msgid "Regular expression too big" +msgstr "ËÜèị̈ êáíïíéễ Ưêöñáóç `%s': %s" + +#: lib/regex.c:1067 +msgid "Unmatched ) or \\)" +msgstr "" + +#: lib/regex.c:5564 +#, fuzzy +msgid "No previous regular expression" +msgstr "ÓöÜë́á óôï ôáßñéáó́á óôçí êáíïíéễ Ưêöñáóç `%s'" + +#: src/builtin.c:349 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Đñïåéäïđïßçóç: Đïëư ëßăá ïñßó́áôá óôï åóùäḯḉƯíï `%s'" + +#: src/builtin.c:355 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "Đñïåéäïđïßçóç: ÅđéđëƯïí ïñßó́áôá óôï åóùäḯḉƯíï `%s' áăíï̃èçêáí" + +#: src/builtin.c:383 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "̀ç-áñè́çôéêü üñéó́á óôï åóùäḯḉƯíï `%s'" + +#: src/builtin.c:494 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "" +"ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôưđị̈ äåäḯƯíïơ áíôéêåé́Ưíïơ óôï define_macro ()" + +#: src/builtin.c:681 src/builtin.c:780 src/builtin.c:1423 src/builtin.c:1447 +#, c-format +msgid "Undefined name %s" +msgstr "̀ç ïñéó́Ưíï üíḯá %s" + +#: src/builtin.c:721 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ÅóùäḯḉƯíï äå âñƯèçêå óôï đßíáêá åóùäḯḉƯíùí!" + +#: src/builtin.c:729 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôưđị̈ äåäḯƯíïơ áíôéêåé́Ưíïơ óôï m4_dumpdef ()" + +#: src/builtin.c:804 +#, fuzzy, c-format +msgid "Undefined name `%s'" +msgstr "̀ç ïñéó́Ưíï üíḯá %s" + +#: src/builtin.c:842 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôưđị̈ óớâüëïơ óôï m4_defn ()" + +#: src/builtin.c:908 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Áäơíá́ßá áíïßắáôị̈ óùë̃íùóç̣ óôçí åíôïë̃ `%s'" + +#: src/builtin.c:948 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Ç âÜóç óôçí áđïôß́çóç åßíáé åêôụ̈ ïñßïơ (âÜóç = %d)" + +#: src/builtin.c:957 +msgid "Negative width to eval" +msgstr "Áñíçôéêü đëÜôị̈ óôçí áđïôß́çóç" + +#: src/builtin.c:1063 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "̀ç áñéè́çôéêü üñéó́á óôï %s" + +#: src/builtin.c:1075 +#, c-format +msgid "Cannot undivert %s" +msgstr "Áäơíá́ßá åđáíáöïñỤ̈ ôïơ %s" + +#: src/builtin.c:1223 +#, c-format +msgid "Undefined syntax code %c" +msgstr "̀ç ïñéó́Ưíị̈ ê₫äéêạ́ óưíôáîç̣ %c" + +#: src/builtin.c:1274 src/freeze.c:211 +#, c-format +msgid "Cannot open %s" +msgstr "Áäơíá́ßá áíïßắáôị̈ ôïơ %s" + +#: src/builtin.c:1483 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "ÊáôÜóôáóç áđïóöáë́Üôùóç̣: ëÜèị̈ óḉáßạ̊ áđïóöáë́Üôùóç̣: `%s'" + +#: src/builtin.c:1519 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Áäơíá́ßá ñưè́éóç̣ ôïơ áñ÷åßïơ óöáë́Üôùí: %s" + +#: src/builtin.c:1740 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "" +"ĐÑÏÅÉÄÏĐÏÉÇÓÇ: Ôï \\0 èá åîáöáíéóôåß, êÜíåôå ÷ñ̃óç ôïơ \\& áíôßèåôá óôẹ́ " +"áíôéêáôáóôÜóåẹ́" + +#: src/builtin.c:1801 src/builtin.c:1861 src/input.c:1014 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "ËÜèị̈ êáíïíéễ Ưêöñáóç `%s': %s" + +#: src/builtin.c:1812 src/builtin.c:1885 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "ÓöÜë́á óôï ôáßñéáó́á óôçí êáíïíéễ Ưêöñáóç `%s'" + +#: src/debug.c:380 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ÅóùäḯḉƯíï äåí âñƯèçêå óôï đßíáêá åóùäḯḉƯíùí! " +"(trace_pre ())" + +#: src/debug.c:388 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôưđị̈ äåäḯƯíïơ áíôéêåé́Ưíïơ (trace_pre ())" + +#: src/eval.c:309 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "ËÜèị̈ Ưêöñáóç óôçí áđïôß́çóç (ëåßđåé äåîéÜ đáñƯíèåóç): %s" + +#: src/eval.c:315 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "ËÜèị̈ Ưêöñáóç óôçí áđïôß́çóç: %s" + +#: src/eval.c:320 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "ËÜèị̈ Ưêöñáóç óôçí áđïôß́çóç (ëÜèị̈ åßóïäị̈): %s" + +#: src/eval.c:325 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "ËÜèị̈ Ưêöñáóç óôçí áđïôß́çóç (ơđåñâïëéễ åßóïäị̈): %s" + +#: src/eval.c:330 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "Äéáßñåóç ́å ́çäƯí óôçí áđïôß́çóç: %s" + +#: src/eval.c:335 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Ơđüëïéđï ́å ́çäƯí óôçí áđïôß́çóç: %s" + +#: src/eval.c:340 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ê₫äéêạ́ óöÜë́áôị̈ óôçí evaluate ()" + +#: src/eval.c:594 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôåëåóộ̃ óưăêñéóç̣ óôï cmp_term ()" + +#: src/eval.c:639 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôåëåóộ̃ ïëßóèçóç̣ óôï shift_term ()" + +#: src/eval.c:738 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôåëåóộ̃ óôï mult_term ()" + +#: src/freeze.c:119 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ÅóùäḯḉƯíï äå âñƯèçêå óôï đßíáêá åóùäḯḉƯíùí!" + +#: src/freeze.c:132 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "" +"ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ ôưđị̈ äåäḯƯíïơ áíôéêåé́Ưíïơ óôï freeze_one_symbol ()" + +#: src/freeze.c:163 +msgid "Expecting line feed in frozen file" +msgstr "Áíá́åíüôáí `line feed' óôï đáăù́Ưíï áñ÷åßï" + +#: src/freeze.c:165 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Áíá́åíüôáí ÷áñáêỗñạ́ `%c' óôï đáăù́Ưíï áñ÷åßï" + +#: src/freeze.c:222 +msgid "Ill-formated frozen file" +msgstr "Êáêü-́ïñöïđïéḉƯíï đáăù́Ưíï áñ÷åßï" + +#: src/freeze.c:277 src/freeze.c:293 +msgid "Premature end of frozen file" +msgstr "Đñüùñï ôƯëị̈ đáăù́Ưíïơ áñ÷åßïơ" + +#: src/freeze.c:327 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "ôï `%s' áđü đáăù́Ưíï áñ÷åßï äå âñƯèçêå óôïí đßíáêá åóùäḯḉƯíùí" + +#: src/input.c:318 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Ç åßóïäị̈ åđáíáöƯñèçêå óôï %s, ăñá́́̃ %d" + +#: src/input.c:346 +#, c-format +msgid "Input read from %s" +msgstr "Ç åßóïäị̈ áíáăí₫óôçêå áđü ôï %s" + +#: src/input.c:506 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: Áíáäñḯéêü push_string!" + +#: src/input.c:623 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: Êáễ êë̃óç óôï init_macro_token ()" + +#: src/input.c:663 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: Áëëïßùóç óôïßâạ́ åéóüäïơ óôï next_char ()" + +#: src/input.c:700 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: Áëëïßùóç óôïßâạ́ åéóüäïơ óôï peek_input ()" + +#: src/input.c:805 +msgid "NONE" +msgstr "ÊÁÍÅÍÁ" + +#: src/input.c:1199 src/input.c:1226 +msgid "ERROR: EOF in string" +msgstr "ÓÖÁË̀Á: EOF óôï áëöáñéè́çôéêü" + +#: src/m4.c:119 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "ÓÖÁË̀Á: Ơđåñ÷åßëçóç óôïßâạ́. (Áíáäñḯ̃ áđåßñïơ âÜèïợ;)" + +#: src/m4.c:146 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Äïêé́Üóôå `%s --help' ăéá đåñéóóüôåñç âï̃èåéá.\n" + +#: src/m4.c:150 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "×ñ̃óç: %s [ÅĐÉËÏĂÇ]... [ÁÑ×ÅÉÏ]...\n" + +#: src/m4.c:151 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Ơđï÷ñåùôéêÜ ̃ đñïáéñåôéêÜ ïñßó́áôá óå ́áêñỰ åđéëïăỰ åßíáé ơđï÷ñåùôéêÜ ̃ " +"đñïáéñåôéêÜ\n" +"êáé ăéá ôç̣ óưíôḯạ̊ åđéëïăỰ åđßóåẹ́.\n" +"\n" +"ÊáôáóôÜóåẹ́ ëåéôïơñăßạ́:\n" +" --help ǻöÜíéóç áơộ̃ ôç̣ âï̃èåéạ́ êáé Ưîïäị̈\n" +" --version ǻöÜíéóç đëçñïöïñé₫í Ưêäïóç̣ êáé Ưîïäị̈\n" +" -e, --interactive Ưîïäị̈ ÷ùñß̣ åíôá́éåơỗ, áăíüçóç äéáêïđ₫í\n" +" -E, --fatal-warnings äéáêïđ̃ åêôƯëåóç̣ ́åôÜ áđü ôç đñ₫ôç " +"đñïåéäïđïßçóç\n" +" -Q, --quiet, --silent áđüêñơøç ́åñéê₫í đñïåéäïđïé̃óåùí óôá " +"åóùäḯḉƯíá\n" +" -P, --prefix-builtins åđéâïë̃ đñïèỨáôị̈ `m4_' óå üëá ôá " +"åóùäḯḉƯíá\n" + +#: src/m4.c:164 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" +" -W --word-regexp=ÊÁÍÅÊÖ ÷ñ̃óç ÊÁÍïíéệ̃ ¸ÊÖñáóç̣ óôï óơíôáêôéêü ôç̣ " +"́áêñïåíôïẹ̈̃\n" + +#: src/m4.c:169 +msgid "" +"\n" +"Dynamic loading features:\n" +" -m, --module-directory=DIRECTORY add DIRECTORY to the module search path\n" +" -M, --load-module=MODULE load dynamic MODULE from M4MODPATH\n" +msgstr "" + +#: src/m4.c:176 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"×áñáêôçñéóôéêÜ đñïåđåîåñăáóỗ:\n" +" -I, --include=ÊÁÔÁËÏĂÏÓ øÜîé́ï ́åôÜ êáé óôï êáôÜëïăï áơôü ăéá " +"đåñéëá́âáíǘåíá\n" +" -D, --define=ÏÍÏ̀Á[=ÔÉ̀Ç] åéóáăùẵ Ïͼ́áôị̈ ́å ÔÉ̀Ç, ̃ êåíü\n" +" -U, --undefine=ÏÍÏ̀Á äéáăñáö̃ åóùäḯḉƯíïơ Ïͼ̀Áôị̈\n" +" -s, --synclines äḉéïơñăßá ăñá́́₫í `#line ÁÑÉÈ̀ÏÓ " +"\"ÁÑ×ÅÉÏ\"'\n" + +#: src/m4.c:184 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"¸ëåă÷ị̈ đåñéïñéó́₫í:\n" +" -G, --traditional áđüêñơøç üëùí ôùí åđåêôÜóåùí GNU\n" +" -H, --hashsize=ĐÑÙÔÏÓ ïñéó́ụ̈ ́åăƯèïợ đßíáêá áíáæ̃ôçóç̣ óớâüëïơ\n" +" -L, --nesting-limit=ÁÑÉÈ̀ÏÓ áëëáẵ ôå÷íçôïư ïñßïơ öùëéáó́₫í\n" + +#: src/m4.c:191 +msgid "" +"\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" +msgstr "" +"\n" +"Áñ÷åßá đáăù́Ưíç̣ êáôÜóôáóç̣:\n" +" -F, --freeze-state=ARXEIO äḉéïơñăßá đáăù́Ưíç̣ êáôÜóôáóç̣ óôï ÁÑ×ÅÉÏ " +"óôï ôƯëị̈\n" +" -R, --reload-state=ARXEIO öüñôù́á îáíÜ đáăù́Ưíç̣ êáôÜóôáóç̣ áđü ÁÑ×ÅÉÏ " +"óôçí åêêßíçóç\n" + +#: src/m4.c:197 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Åêóöáë́Üôùóç:\n" +" -d, --debug=[ÓÇ̀ÁÉÅÓ] ïñéó́ụ̈ åđéđƯäïơ åêóöáë́Üôùóç̣ (÷ùñß̣ ÓÇ̀ÁÉÅÓ " +"ơđïíïåß `aeq')\n" +" -t, --trace=ONOMA áíß÷íåơóç Ïͼ̀Áôị̈ üôáí áơôü èá ïñéóôåß\n" +" -l, --arglength=ÁÑÉÈ̀ đåñéïñéó́ụ̈ ́åăƯèïợ áíß÷íåơóç̣ ́áêñïåíôïẹ̈̃\n" +" -o, --error-output=ÁÑ×ÅÉÏ åđáíáêáôåưèơíóç åîüäïơ åêóöáë́Üôùóç̣ êáé " +"áíß÷íåơóç̣\n" + +#: src/m4.c:205 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"ÓÇ̀ÁÉÅÓ ́đïñåß íá åßíáé ïđïéä̃đïôå áđü:\n" +" t áíß÷íåơóç üëùí ôùí êë̃óåùí ôùí ́áêñïåíôïë₫í, ü÷é ́üíï áơôỰ đïơ Ư÷ïơí " +"ïñéóôåß\n" +" a ǻöÜíéóç đñáắáôéê₫í ïñéó́Üôùí\n" +" e ǻöÜíéóç áíÜđôơîç̣\n" +" q đáñÜèåóå ôé́Ự üđụ̀ ÷ñåéÜæåôáé, ́å ôẹ́ óḉáßạ̊ a ̃ e\n" +" c ǻöÜíéóç đñéí ôç óơëëïẵ, ́åôÜ ôç óơëëïẵ êáé ́åôÜ ôç êë̃óç\n" +" x đñüóèåóç ́ïíáäéệ̃ ôáơôüôçôạ́ êë̃óç̣ ́áêñïåíôïẹ̈̃, ÷ñ̃óé́ï ́å ôç " +"óḉáßá c\n" +" f ǻöÜíéóç ôñƯ÷ïíôị̈ ïíǘáôị̈ áñ÷åßïơ åéóüäïơ\n" +" l ǻöÜíéóç áñéè́ü ôñå÷ïưóç̣ ăñạ́́́̃ åéóüäïơ\n" +" p ǻöÜíéóç áđïôåëåó́Üôùí áđü Ưñåơíạ̊ óôï ́ïíïđÜôé\n" +" i ǻöÜíéóç áëëáă₫í óôá áñ÷åßá åéóüäïơ\n" +" V óơíôḯïăñáößá ăéá üëạ̊ ôẹ́ đáñáđÜíù óḉáßạ̊\n" + +#: src/m4.c:220 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"×ùñß̣ ÁÑ×ÅÉÏ, ̃ üôáí ôï áñ÷åßï åßíáé ôï -, áíÜăíùóç áđü ôçí êáíïíéễ " +"åßóïäï.\n" + +#: src/m4.c:225 +msgid "" +"\n" +"Report bugs to <bug-m4@gnu.org>.\n" +msgstr "" +"\n" +"ÁíáöƯñáôå óöÜë́áôá óôï <bug-m4@gnu.org>.\n" + +#: src/m4.c:414 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "ËÜèị̈ óḉáßạ̊ åêóöáë́Üôùóç̣: `%s'" + +#: src/m4.c:436 +#, c-format +msgid "ERROR: failed to add search directory `%s'" +msgstr "" + +#: src/m4.c:440 +#, c-format +msgid "ERROR: failed to add search directory `%s': %s" +msgstr "" + +#: src/m4.c:460 +msgid " (options:" +msgstr " (åđéëïăỰ:" + +#: src/m4.c:542 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ êùäéêụ̈ óôá áíáöåñǘåíá ïñßó́áôá" + +#: src/macro.c:97 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ åßäị̈ áíôéêåé́Ưíïơ óôï expand_token ()" + +#: src/macro.c:163 +msgid "ERROR: EOF in argument list" +msgstr "ÓÖÁË̀Á: EOF óôç ëßóôá ïñéó́Üôùí" + +#: src/macro.c:182 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ åßäị̈ áíôéêåé́Ưíïơ óôï expand_argument ()" + +#: src/macro.c:259 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: ËÜèị̈ åßäị̈ óớâüëïơ óôï call_macro ()" + +#: src/macro.c:288 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "" +"ÓÖÁË̀Á: Ôï üñéï áíáäñị̈́̃ %d îåđåñÜóôçêå, êÜíôå ÷ñ̃óç ôïơ -L<N> ăéá íá ôï " +"áëëÜîåôå" + +#: src/module.c:123 +#, fuzzy, c-format +msgid "ERROR: failed to initialise modules: %s" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s': %s" + +#: src/module.c:221 +#, fuzzy, c-format +msgid "ERROR: cannot find module: `%s'" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s'" + +#: src/module.c:224 +#, fuzzy, c-format +msgid "ERROR: cannot find module: `%s': %s" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s': %s" + +#: src/module.c:274 +#, fuzzy +msgid "ERROR: cannot close modules" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s'" + +#: src/module.c:277 +#, fuzzy, c-format +msgid "ERROR: cannot cannot close modules: %s" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s': %s" + +#: src/module.c:284 +#, fuzzy, c-format +msgid "ERROR: cannot close module: `%s'" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s'" + +#: src/module.c:288 +#, fuzzy, c-format +msgid "ERROR: cannot cannot close module: `%s': %s" +msgstr "ÓÖÁË̀Á: áäơíá́ßá åưñåóç̣ Üñèñùóç̣ `%s': %s" + +#: src/output.c:262 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "ÓÖÁË̀Á: Áäơíá́ßá äḉéïơñăßạ́ đñïóùñéíïư áñ÷åßïơ ăéá áëëáẵ" + +#: src/output.c:272 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "ÓÖÁË̀Á: Áäơíá́ßá áđïóôïẹ̈̃ áëëáặ̃ óôï đñïóùñéíü áñ÷åßï" + +#: src/output.c:356 +msgid "ERROR: Copying inserted file" +msgstr "ÓÖÁË̀Á: Áíôéăñáẵ åéóåñ÷ḯƯíïơ áñ÷åßïơ" + +#: src/output.c:537 +msgid "ERROR: Reading inserted file" +msgstr "ÓÖÁË̀Á: ÁíÜăíùóç åéóåñ÷ḯƯíïơ áñ÷åßïơ" + +#: src/output.c:636 +msgid "Cannot stat diversion" +msgstr "Áäơíá́ßá đñïóđƯëáóç̣ ôïơ áñ÷åßïơ ôç̣ áëëáặ̃" + +#: src/output.c:639 +msgid "Diversion too large" +msgstr "" + +#: src/path.c:157 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "Ï Ưëåă÷ị̈ ́ïíïđáôéïư ăéá ôï `%s' âñ̃êå `%s'" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:175 +msgid "VMEM limit exceeded?\n" +msgstr "Ôï üñéï ôç̣ åéêïíéễ ́í̃́ç̣ åîáíôë̃èçêå;\n" + +#: src/stackovf.c:197 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Åíôïđßóôçêå đáñÜâáóç ôùí ïñßùí ́í̃́ç̣ (SIGSEGV). Åßôå Ưăéíå ơđƯñâáóç " +"óôïßâạ́\n" +"åßôå ơđÜñ÷åé óöÜë́á đñïăñǗ́áôị̈ óôï " + +#: src/stackovf.c:202 +msgid ". Check for possible infinite recursion.\n" +msgstr ". ÅëƯăîáôå ăéá đéèáí̃ åđ'Üđåéñï áíáäñḯ̃.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "ÅÓÙÔÅÑÉÊÏ ÓÖÁË̀Á: Áíôéêáíïíéễ êáôÜóôáóç óôï symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Ôï üíḯá `%s' åßíáé Üăíùóôï\n" + +#~ msgid "Undefined macro `%s'" +#~ msgstr "̀ç ïñéó́Ưíç ́áêñïåíôïë̃ `%s'" + +#~ msgid "Module search for `%s' found `%s'" +#~ msgstr "Ç Ưñåơíá Üñèñùóç̣ ăéá `%s' âñ̃êå `%s'" diff --git a/po/fr.gmo b/po/fr.gmo Binary files differnew file mode 100644 index 00000000..8707d3ea --- /dev/null +++ b/po/fr.gmo diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 00000000..85b66092 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,468 @@ +# French messages for GNU m4. +# Copyright (C) 1998 Free Software Foundation, Inc. +# Erick Branderhorst <Erick.Branderhorst@asml.nl>, 1998, +# created this file based on fr.msg, which was created by: +# Franc,ois Pinard <pinard@iro.umontreal.ca> 199(4-7). +# +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4d\n" +"POT-Creation-Date: 1998-05-25 12:26+0200\n" +"PO-Revision-Date: 1998-05-23 11:53+02:00\n" +"Last-Translator: Erick Branderhorst <Erick.Branderhorst@asml.nl>\n" +"Language-Team: dutch <nl@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:272 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Attention: Trop peu d'arguments pour «%s» prédéfini" + +#: src/builtin.c:278 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "Attention: Les arguments superflus pour «%s» prédéfini sont ignorés" + +#: src/builtin.c:298 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Argument non-numérique pour «%s» prédéfini" + +#: src/builtin.c:438 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "ERREUR INTERNE: Mauvais type de lexème dans define_macro ()" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, c-format +msgid "Undefined name %s" +msgstr "Nom «%s» non-défini" + +#: src/builtin.c:636 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "ERREUR INTERNE: Prédéfini introuvable dans la table des prédéfinis!" + +#: src/builtin.c:644 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "ERREUR INTERNE: Mauvais type de données pour lexème dans m4_dumpdef ()" + +#: src/builtin.c:695 +#, c-format +msgid "Undefined macro `%s'" +msgstr "Macro «%s» non-défini" + +#: src/builtin.c:735 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "ERREUR INTERNE: Mauvais type de symbole dans m4_defn ()" + +#: src/builtin.c:772 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Incapable d'ouvrir un «pipe» pour la commande «%s»" + +#: src/builtin.c:811 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Base hors intervalle dans «eval» (base = %d)" + +#: src/builtin.c:820 +msgid "Negative width to eval" +msgstr "Largeur négative dans «eval»" + +#: src/builtin.c:925 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "Argument non-numérique pour %s" + +#: src/builtin.c:937 +#, c-format +msgid "Cannot undivert %s" +msgstr "Incapble de ramener la diversion %s" + +#: src/builtin.c:1043 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "Incapable d'ouvrir %s" + +#: src/builtin.c:1248 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Debugmode: mauvais indicateurs de mise-au-point: «%s»" + +#: src/builtin.c:1284 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Incapable de préparer le fichier d'erreurs: %s" + +#: src/builtin.c:1501 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "" +"ATTENTION: \\\\0 disparaîtra, utiliser \\\\& plutôt pour les remplacements" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "Mauvaise expression régulière «%s»: %s" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "Erreur d'appariement pour l'expressio régulière «%s»" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"ERREUR INTERNE: Prédéfini introuvable dans la table des prédéfinis! " +"(trace_pre ())" + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "ERREUR INTERNE: Mauvais type de donnée pour de lexème (trace_pre ())" + +#: src/eval.c:277 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "Mauvaise expression dans «eval» (parenthèse droite manquante): %s" + +#: src/eval.c:283 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "Mauvaise expression dans «eval»: %s" + +#: src/eval.c:288 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "Mauvaise expression dans «eval» (mauvaise entrée): %s" + +#: src/eval.c:293 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "Mauvaise expression dans «eval» (entrée superflue): %s" + +#: src/eval.c:298 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "Division par zéro dans «eval»: %s" + +#: src/eval.c:303 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Module par zéro dans «eval»: %s" + +#: src/eval.c:308 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "ERREUR INTERNE: Mauvais code d'erreur dans evaluate ()" + +#: src/eval.c:547 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "ERREUR INTERNE: Mauvais opérateur de comparaison dans cmp_term ()" + +#: src/eval.c:590 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "ERREUR INTERNE: Mauvais opérateur de décalage dans shift_term ()" + +#: src/eval.c:674 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "ERREUR INTERNE: Mauvais opérateur dans mult_term ()" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "ERREUR INTERNE: Prédéfini introuvable dans la table des prédéfinis!" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "" +"ERREUR INTERNE: Mauvais type de donnée pour lexème dans freeze_one_symbol ()" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "Fin-de-ligne attendue du fichier figé" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Caractère «%c» attendu du fichier figé" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "Fichier figé difforme" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "Fin prématurée de fichier figé" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "" +"«%s» dans le fichier figé est introuvable dans la table des prédéfinis!" + +#: src/input.c:174 +#, c-format +msgid "Input read from %s" +msgstr "Entrée lue de %s" + +#: src/input.c:231 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "ERREUR INTERNE: Utilisation récursive de push_string!" + +#: src/input.c:311 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Entrée reprise de %s, ligne %d" + +#: src/input.c:325 +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "ERREUR INTERNE: Pile d'entrée douteuse dans pop_input ()" + +#: src/input.c:364 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "ERREUR INTERNE: Mauvais appel à init_macro_token ()" + +#: src/input.c:413 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "ERREUR INTERNE: Pile d'entrée douteuse dans peek_input ()" + +#: src/input.c:470 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "ERREUR INTERNE: Pile d'entrée douteuse dans next_char ()" + +#: src/input.c:550 +msgid "NONE" +msgstr "AUCUN" + +#: src/input.c:777 +msgid "ERROR: EOF in string" +msgstr "ERREUR: Fin-de-fichier dans la chaîne" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "ERREUR INTERNE: Mauvais type de lexème dans expand_token ()" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Pour plus d'information, essayez «%s --help».\\n\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "Usage: %s [OPTION]... [FICHIER]...\\n\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Les arguments obligatoires ou optionnels pour la forme longue des\n" +"options sont aussi obligatoires ou optionnels pour les formes courtes\n" +"qui leur correspondent.\n" +"\n" +"Modes d'opération:\n" +" --help fournir ce message d'aide, puis terminer\n" +" --version identifier le programme, puis terminer\n" +" -e, --interactive ne pas tamponner, ignorer les interruptions\n" +" -E, --fatal-warnings terminer l'exécution après le moindre " +"message\n" +" -Q, --quiet, --silent inhiber certains diagnostics prédéfinis\n" +" -P, --prefix-builtins préfixer tous les prédéfinis par «m4_»\n" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" +" -W, --word-regexp=REGEXP utiliser REGEXP pour les noms de macro\n" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"Capacités de préprocesseur:\n" +" -I, --include=REPERTOIRE ensuite fouiller ce répertoire d'inclusions\n" +" -D, --define=NOM[=VALEUR] définir NOM comme ayant VALEUR (ou vide)\n" +" -U, --undefine=NOM éliminer le NOM prédéfini\n" +" -s, --synclines engendrer des lignes «#line NNN " +"\\\"FICHIER\\\"»\n" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"Contrôle des limites:\n" +" -G, --traditional inhiber toutes les extensions GNU\n" +" -H, --hashsize=PREMIER choisir la grandeur de la table de symboles\n" +" -L, --nesting-limit=NOMBRE modifier la limite artificielle " +"d'imbrication\n" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" +"\n" +"Fichiers d'état figé:\n" +" -F, --freeze-state=FICHIER produire un FICHIER figé à la fin\n" +" -R, --reload-state=FICHIER recharger un FICHIER figé au départ\n" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Mise-au-point:\n" +" -d, --debug=[INDICS] niveau de mise-au-point (implicitement " +"«aeq»)\n" +" -t, --trace=NOM tracer NOM lorsqu'il sera défini\n" +" -l, --arglength=NOMBRE restreindre la grandeur de trace des macros\n" +" -o, --error-output=FICHIER rediriger la sortie de trace et " +"mise-au-point\n" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"INDICS est une combinaison de:\n" +" t tracer tous les appels de macro, pas uniquement les «traceon»\n" +" a afficher les arguments véritables\n" +" e afficher le résultat de l'expension\n" +" q mettre entre guillemets lorsque necessaire, avec indics «a» ou «e»\n" +" c afficher avant et après la collecte, puis après l'appel\n" +" x ajouter une identification unique, utile avec l'indicateur «c»\n" +" f donner le nom courant du fichier d'entrée\n" +" l donner le numéro de la ligne d'entrée\n" +" p afficher les résultats des fouilles de chemin\n" +" i afficher les modifications dans les fichiers d'entrée\n" +" V abbréviation commode pour toutes les options précédentes à la fois\n" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"Si aucun FICHIER ou si FICHIER vaut «-», lit l'entrée standard.\n" + +#: src/m4.c:355 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "Mauvais indicateurs de mise-au-point: «%s»" + +#: src/m4.c:434 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "ERREUR INTERNE: Mauvais code dans les arguments différés" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "ERREUR: Débordement de pile. (Récursion hors contrôle sur «define»?)" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "ERREUR: Fin-de-fichier dans la liste d'arguments" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "" +"ERREUR INTERNE: Mauvais type de données pour lexème dans expand_argument ()" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "ERREUR INTERNE: Mauvais type de symbole dans call_macro ()" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "ERREUR: Limite de récursion %d dépassée, la changer par -L<N>" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "ERREUR: Incapable de créer un fichier temporaire pour la diversion" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "ERREUR: Incapable de vider la diversion sur un fichier temporaire" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "ERREUR: Pendant la copie du fichier inséré" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "ERREUR: Pendant la lecture d'un fichier inséré" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "Incapable d'opérer «stat» pour la diversion" + +#: src/path.c:131 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "La fouille du chemin pour «%s» trouve «%s»" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "Limit VMEM outrepassée?\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Les violations de mémoire sont détectées (SIGSEGV). Ou bien la pile a\n" +"débordé, ou bien il y a un problème dans " + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". Vérifier une récursion hors contrôle.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "ERREUR INTERNE: Mode illégal dans symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Le nom «%s» est inconnu\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "Mauvaise expression régulière: «%s»: %s" diff --git a/po/it.gmo b/po/it.gmo Binary files differnew file mode 100644 index 00000000..106f8cc8 --- /dev/null +++ b/po/it.gmo diff --git a/po/it.po b/po/it.po new file mode 100644 index 00000000..cbc04699 --- /dev/null +++ b/po/it.po @@ -0,0 +1,406 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 1998-08-03 17:14+0200\n" +"Version: \n" +"Date: 1995-06-30 21:00:12+0200\n" +"From: Ulrich Drepper <drepper@myware>\n" +"Xgettext-Options: --default-domain=m4 --output-dir=. --add-comments " +"--keyword=_\n" +"Files: ../src/builtin.c ../src/debug.c ../src/eval.c ../src/freeze.c\n" +"Files: ../src/input.c ../src/m4.c ../src/macro.c ../src/output.c\n" +"Files: ../src/path.c ../src/stackovf.c ../src/symtab.c ../lib/getopt.c\n" +"Files: ../lib/regex.c ../lib/xmalloc.c\n" +"Update on Fri Jun 30 21:00:27 MET 1995 \n" + +#: src/builtin.c:272 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Attenzione: Troppo pochi argomenti per la funzione predefinita `%s'" + +#: src/builtin.c:278 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "" +"Attenzione: Gli argumenti in eccesso alla funzione predefinita `%s' sono " +"ignorati" + +#: src/builtin.c:298 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Argumento non numerico a funzione predefinita `%s'" + +#: src/builtin.c:438 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "ERRORE INTERNO: Tipo dato `token' errato in define_macro ()" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, c-format +msgid "Undefined name %s" +msgstr "Nome `%s' non definito" + +#: src/builtin.c:636 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "" + +#: src/builtin.c:644 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "" + +#: src/builtin.c:695 +#, c-format +msgid "Undefined macro `%s'" +msgstr "Macro `%s' non definita" + +#: src/builtin.c:735 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "ERRORE INTERNO: Tipo simbolo errato in m4_defn ()" + +#: src/builtin.c:772 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Impossibile aprire una `pipe' per il comando `%s'" + +#: src/builtin.c:811 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Base fuori intervallo in `eval' (base = %d)" + +#: src/builtin.c:820 +msgid "Negative width to eval" +msgstr "Larghezza negativa in `eval'" + +#: src/builtin.c:925 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "Argumento non numerico a %s" + +#: src/builtin.c:937 +#, c-format +msgid "Cannot undivert %s" +msgstr "Impossibile ripristinare la deviazione %s" + +#: src/builtin.c:1043 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "Impossibile aprire %s" + +#: src/builtin.c:1248 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Modalità di debug: indicatori di debug errati: `%s'" + +#: src/builtin.c:1284 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Impossibile aprire l' archivio di errore: %s" + +#: src/builtin.c:1501 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "Espressione regolare errata `%s': %s" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "Errore nel confronto dell' espressione regolare `%s'" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "" + +#: src/eval.c:277 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "Espressione errata in `eval' (manca la parentesi destra): %s" + +#: src/eval.c:283 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "Espressione errata in `eval': %s" + +#: src/eval.c:288 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "Espressione errata in `eval' (testo errato): %s" + +#: src/eval.c:293 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "Espressione errata in `eval' (testo in eccesso): %s" + +#: src/eval.c:298 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "Divisione per zero in `eval': %s" + +#: src/eval.c:303 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Modulo zero in `eval': %s" + +#: src/eval.c:308 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "ERRORE INTERNO: Code di errore errato in evaluate ()" + +#: src/eval.c:547 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "" + +#: src/eval.c:590 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "" + +#: src/eval.c:674 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "ERRORE INTERNO: Operatore errato in mult_term ()" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "Atteso il carattere di fine linea in archivio congelato" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Atteso il carattere `%c' in archivio congelato" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "Archivio congelato malformato" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "Fine prematura dell' archivio congelato" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "" + +#: src/input.c:174 +#, c-format +msgid "Input read from %s" +msgstr "Errore di lettura da %s" + +#: src/input.c:231 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "ERRORE INTERNO: Utilizzo ricorsivo di push_string!" + +#: src/input.c:311 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Ingresso ripristinato su %s, linea %d" + +#: src/input.c:325 +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "ERRORE INTERNO: Stack di ingresso corrotto in pop_input ()" + +#: src/input.c:364 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "ERRORE INTERNO: Chiamata errata a init_macro_token ()" + +#: src/input.c:413 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "ERRORE INTERNO: Stack di ingresso corrotto in peek_input ()" + +#: src/input.c:470 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "ERRORE INTERNO: Stack di ingresso corrotto in next_char ()" + +#: src/input.c:550 +msgid "NONE" +msgstr "NESSUNO" + +#: src/input.c:777 +msgid "ERROR: EOF in string" +msgstr "ERRORE: Fine prematura di una stringa" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "ERRORE: Stack overflow. (Ricorsione infinita in `define'?)" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Per ulteriori informazioni provare `%s --help'.\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "Usage: %s [OPZIONE]... [ARCHIVIO]...\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" + +#: src/m4.c:358 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "Indicatori di debug errati: `%s'" + +#: src/m4.c:437 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "ERRORE INTERNO: Codice errato in argomenti differiti" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "ERRORE INTERNO: Tipo `token' errato in expand_token ()" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "ERRORE: Fine prematura della lista di argomenti" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "ERRORE INTERNO: Tipo simbolo errato in call_macro ()" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "ERRORE: Impossibile creare un archivio temporaneo per la deviazione" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "ERRORE: Impossibile terminare la deviazione su file temporaneo" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "ERRORE: Copiando archivio inserito" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "ERRORE: Leggendo archivio inserito" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "Impossibile effettuare la `stat' per la deviazione" + +#: src/path.c:131 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "La ricerca del percorso per `%s' ha trovato `%s'" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "Limite di VMEM superato?\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". Controllare una possibile ricorsione infinita.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "ERRORE INTERNO: Modo illegale in symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Il nome `%s' è sconosciuto\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "Espressione regolare errata: `%s': %s" diff --git a/po/ja.gmo b/po/ja.gmo Binary files differnew file mode 100644 index 00000000..da665805 --- /dev/null +++ b/po/ja.gmo diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 00000000..f5bf54dd --- /dev/null +++ b/po/ja.po @@ -0,0 +1,515 @@ +# Japanese messages for GNU m4. +# Copyright (C) 1996 Free Software Foundation, Inc. +# Akiko Matsushita <matusita@sra.co.jp>, 1996. +# +msgid "" +msgstr "" +"Project-Id-Version: GNU m4 1.4.3\n" +"POT-Creation-Date: 1998-08-03 17:14+0200\n" +"PO-Revision-Date: 1996-03-28 11:52 EST\n" +"Last-Translator: Akiko Matsushita <matusita@sra.co.jp>\n" +"Language-Team: Japanese <ja@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=EUC\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:272 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "·Ù¹đ¡§%s ¤Ø¤Î°ú¿ô¤¬ÉÔ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/builtin.c:278 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "·Ù¹đ¡§%s ¤Ø¤Î°ú¿ô¤¬Â¿²á¤®¤̃¤¹ (Ķ¤¨¤¿Ê¬¤Ï̀µ»ë¤µ¤́¤̃¤¹)¡£" + +#: src/builtin.c:298 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "`%s' ¤Ë¿ô»ú¤Ç¤Ê¤¤°ú¿ô¤¬ÅϤµ¤́¤Æ¤¤¤̃¤¹¡£" + +#: src/builtin.c:438 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô define_macro () Æâ¤Î¥È¡¼¥¯¥ó¥Ç¡¼¥¿¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, c-format +msgid "Undefined name %s" +msgstr "`%s' ¤ÏÄêµÁ¤µ¤́¤Æ¤¤¤̃¤»¤ó¡£" + +#: src/builtin.c:636 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "ÆâÉô¥¨¥é¡¼¡§`Built-in' ¤È¤¤¤¦¥Ó¥ë¥È¥¤¥ó¥̃¥¯¥í¤Ï¤¢¤ê¤̃¤»¤ó¡£" + +#: src/builtin.c:644 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô m4_dumpdef () ¤Î¥È¡¼¥¯¥ó¥Ç¡¼¥¿¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/builtin.c:695 +#, c-format +msgid "Undefined macro `%s'" +msgstr "¥̃¥¯¥í `%s' ¤ÏÄêµÁ¤µ¤́¤Æ¤¤¤̃¤»¤ó¡£" + +#: src/builtin.c:735 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô m4_defn () Æâ¤Î¥·¥ó¥Ü¥ë¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/builtin.c:772 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "¥³¥̃¥ó¥É `%s' ¤Ø¤Î¥Ñ¥¤¥×¤¬¥ª¡¼¥×¥ó¤Ç¤¤̃¤»¤ó¡£" + +#: src/builtin.c:811 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "eval ¤Î´đ¿ô ( %d ¿ÊË¡) ¤Î·å¿ô¤¬µöÍÆÈϰϳ°¤Ë¤¢¤ê¤̃¤¹¡£" + +#: src/builtin.c:820 +msgid "Negative width to eval" +msgstr "eval ¤Î½ĐÎÏ·å¿ô¤¬Éé¿ô¤Ë¤Ê¤Ă¤Æ¤¤¤̃¤¹¡£" + +#: src/builtin.c:925 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "`%s' ¤Ë¿ô»ú¤Ç¤Ê¤¤°ú¿ô¤¬ÅϤµ¤́¤Æ¤¤¤̃¤¹¡£" + +#: src/builtin.c:937 +#, c-format +msgid "Cannot undivert %s" +msgstr "`%s' ¤̣ undivert ¤Ç¤¤̃¤»¤ó¡£" + +#: src/builtin.c:1043 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "`%s' ¤̣¥ª¡¼¥×¥ó¤Ç¤¤̃¤»¤ó¡£" + +#: src/builtin.c:1248 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "debugmode ¥̃¥¯¥í¤Ë¤ª¤¤¤Æ %s ¤ÏÉÔÀµ¤Ê¥Ç¥Đ¥Ă¥°¥ª¥×¥·¥ç¥ó¤Ç¤¹¡£" + +#: src/builtin.c:1284 +#, c-format +msgid "Cannot set error file: %s" +msgstr "`%s' ¤̣¥¨¥é¡¼¥í¥°¥Ơ¥¡¥¤¥ë¤È¤·¤Æ¥»¥Ă¥È¤Ç¤¤̃¤»¤ó¡£" + +#: src/builtin.c:1501 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "·Ù¹đ¡§\\0 ¤Ïµ́¼°¤ÎÍÑË¡¤Ç¤¹¡£\\& ¤̣Âå¤ï¤ê¤Ë»È¤Ă¤Æ²¼¤µ¤¤¡£" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "`%s' : %s ¤Ï¡¢ÉÔÀµ¤ÊÀµµ¬É½¸½¤Ç¤¹¡£" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "Àµµ¬É½¸½ %s ¤Î¥̃¥Ă¥Á¥ó¥°¤Ë¼ºÇÔ¤·¤̃¤·¤¿¡£" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"ÆâÉô¥¨¥é¡¼¡§`Builtin' ¤È¤¤¤¦¥Ó¥ë¥È¥¤¥ó¥̃¥¯¥í¤Ï¤¢¤ê¤̃¤»¤ó¡£\n" +" (´Ø¿ô trace_pre () ¤¬¤³¤Î¥¨¥é¡¼¥á¥Ă¥»¡¼¥¸¤̣½Đ¤·¤Æ¤¤¤̃¤¹¡£) " + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "" +"ÆâÉô¥¨¥é¡¼¡§¥È¡¼¥¯¥ó¥Ç¡¼¥¿¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£\n" +" (´Ø¿ô trace_pre () ¤¬¤³¤Î¥¨¥é¡¼¥á¥Ă¥»¡¼¥¸¤̣½Đ¤·¤Æ¤¤¤̃¤¹¡£)" + +#: src/eval.c:277 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "eval ¤Ç %s ¤È¤¤¤¦ÉÔÀµ¤Êɽ¸½¤¬ÍѤ¤¤é¤́¤Æ¤¤¤̃¤¹ (ÊĤ¸³ç¸̀¤¬¤¢¤ê¤̃¤»¤ó)¡£" + +#: src/eval.c:283 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "eval ¤Ç %s ¤È¤¤¤¦ÉÔÀµ¤Ê¼°¤¬ÍѤ¤¤é¤́¤Æ¤¤¤̃¤¹¡£" + +#: src/eval.c:288 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "" +"eval ¤Ç `%s' ¤È¤¤¤¦ÉÔÀµ¤Êɽ¸½¤¬ÍѤ¤¤é¤́¤Æ¤¤¤̃¤¹ \n" +" (Æ₫Îϥǡ¼¥¿¤¬Àµ¤·¤¯¤¢¤ê¤̃¤»¤ó)¡£" + +#: src/eval.c:293 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "eval ¤Ç %s ¤È¤¤¤¦ÉÔÀµ¤Ê¼°¤¬ÍѤ¤¤é¤́¤Æ¤¤¤̃¤¹ (Æ₫Îϥǡ¼¥¿¤¬Â¿²á¤®¤̃¤¹)¡£" + +#: src/eval.c:298 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "`%s' ¤È¤¤¤¦É½¸½¤Ç¡¢0 ¤Ë¤è¤ë³ä»»¤¬¹Ô¤ï¤́¤Æ¤¤¤̃¤¹¡£" + +#: src/eval.c:303 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "`%s' ¤È¤¤¤¦ eval ¤Ç¡¢´đ¿ô¤¬ 0 ¤Ë¤Ê¤Ă¤Æ¤¤¤̃¤¹¡£" + +#: src/eval.c:308 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô evaluate () Æâ¤Î¥¨¥é¡¼¥³¡¼¥É¤¬ÉÔÀµ¤Ç¤¹¡£" + +#: src/eval.c:547 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô cmp_term () ¤ÎÈæ³Ó±é»»»̉¤¬ÉÔÀµ¤Ç¤¹¡£" + +#: src/eval.c:590 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§shift_term () ¤Î¥·¥Ơ¥È±é»»»̉¤¬ÉÔÀµ¤Ç¤¹¡£" + +#: src/eval.c:674 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô mult_term () Æâ¤Î±é»»»̉¤¬ÉÔÀµ¤Ç¤¹¡£" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "ÆâÉô¥¨¥é¡¼¡§`Built-in' ¤È¤¤¤¦¥Ó¥ë¥È¥¤¥ó¥̃¥¯¥í¤Ï¤¢¤ê¤̃¤»¤ó¡£" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "" +"ÆâÉô¥¨¥é¡¼¡§´Ø¿ô freeze_one_symbol () ¤Î¥È¡¼¥¯¥ó¥Ç¡¼¥¿¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "Åà·ë¥Ơ¥¡¥¤¥ëÆâ¤Ç²₫¹Ô¥³¡¼¥É¤̣´üÂÔ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Åà·ë¥Ơ¥¡¥¤¥ëÆâ¤Çʸ»ú `%c' ¤̣´üÂÔ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "ÆâÉô¥¨¥é¡¼¡§Åà·ë¥Ơ¥¡¥¤¥ë¤Î¥Ơ¥©¡¼¥̃¥Ă¥È¤¬ÉÔÀµ¤Ç¤¹¡£" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "Åà·ë¥Ơ¥¡¥¤¥ë¤Î EOF ¤¬Á᤯Íè²á¤®¤Æ¤¤¤̃¤¹¡£" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "Åà·ë¥Ơ¥¡¥¤¥ë¤Î %s ¤Ï¥Ó¥ë¥È¥¤¥ó¥³¥̃¥ó¥É¤Î¥Æ¡¼¥Ö¥ë¤Ë¤Ï¤¢¤ê¤̃¤»¤ó¡£" + +#: src/input.c:174 +#, c-format +msgid "Input read from %s" +msgstr "%s ¤«¤é¤ÎÆ₫ÎϤ̣Æɤ߹₫¤ß¤̃¤¹¡£" + +#: src/input.c:231 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "ÆâÉô¥¨¥é¡¼¡§ºÆµ¢Åª¤Ëʸ»úÎó¤̣ push ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/input.c:311 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "¥Ơ¥¡¥¤¥ë %s, %d ¹Ồܤ«¤éÆ₫ÎϤ·Ä¾¤·¤̃¤¹¡£" + +#: src/input.c:325 +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô pop_input () Æâ¤Ç¥¹¥¿¥Ă¥¯¤ÎÆ₫ÎϤ˼ºÇÔ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/input.c:364 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô init_macro_token () ¤¬ÉÔÀµ¤Ë¸Æ¤Đ¤́¤Æ¤¤¤̃¤¹¡£" + +#: src/input.c:413 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô peek_input () Æâ¤Ç¥¹¥¿¥Ă¥¯¤ÎÆ₫ÎϤ˼ºÇÔ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/input.c:470 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô next_char () Æâ¤Ç¥¹¥¿¥Ă¥¯¤ÎÆ₫ÎϤ˼ºÇÔ¤·¤Æ¤¤¤̃¤¹¡£" + +#: src/input.c:550 +msgid "NONE" +msgstr "¤Ê¤·" + +#: src/input.c:777 +msgid "ERROR: EOF in string" +msgstr "¥¨¥é¡¼: ʸ»úÎóÆâ¤Ë¥Ơ¥¡¥¤¥ë¤Î½ªĂ¼µ¹æ¤¬¤¢¤ê¤̃¤¹¡£" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "" +"¥¨¥é¡¼: ¥¹¥¿¥Ă¥¯¤¬¥ª¡¼¥Đ¡¼¥Ơ¥í¡¼¤̣µ¯¤³¤·¤Æ¤¤¤̃¤¹¡£\n" +" (̀µ¸Â¤ËºÆµ¢ÅªÄêµÁ¤̣¤·¤Æ¤¤¤̃¤»¤ó¤«¡©)" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "¾Ü¤·¤¯¤Ï `%s --help' ¤Î½ĐÎϤ̣¸æÍ÷²¼¤µ¤¤¡£\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "»ÈÍÑÊưË¡: %s [¥ª¥×¥·¥ç¥ó]...[¥Ơ¥¡¥¤¥ë̀¾]\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Ť¤¥ª¥×¥·¥ç¥ó¤¬¼è¤ëɬ¿Ü°ú¿ô¤ª¤è¤ÓÁªẬ²Äǽ¤Ê°ú¿ô¤Ï\n" +"Ă»¤¤¥ª¥×¥·¥ç¥ó¤Î¾́¹ç¤Ë¤âɬÍפǤ¹¡£\n" +"Operation modes:\n" +" --help ¥ª¥×¥·¥ç¥ó¤Î°́Í÷¤̣½ĐÎϤ·¡¢½ªÎ»¤·¤̃¤¹¡£\n" +" --version ¥Đ¡¼¥¸¥ç¥ó¾đÊó¤̣½ĐÎϤ·¡¢½ªÎ»¤·¤̃¤¹¡£\n" +" -e, --interactive " +"½ĐÎϤ̣¥Đ¥Ă¥Ơ¥¡¥ê¥ó¥°¤»¤º¡¢³ä¤ê¹₫¤ß¤̣̀µ»ë¤·¤̃¤¹¡£\n" +" -E, --fatal-warnings ·Ù¹đ¤¬½Đ¤µ¤́¤ë¤È¼Â¹Ô¤̣Ăæ»ß¤·¤̃¤¹¡£\n" +" -Q, --quiet, --silent " +"¤¤¤¯¤Ä¤«¤Î¥Ó¥ë¥È¥¤¥ó¥³¥̃¥ó¥É¤Î·Ù¹đ¤̣Í̃À©¤·¤̃¤¹¡£\n" +" -P, --prefix-builtins Á´¤Æ¤Î¥Ó¥ë¥È¥¤¥ó¥̃¥¯¥í¤Ë `m4_' ¤È¤¤¤¦ÀÜƬ¼¤̣ " +" ¶¯À©Åª¤ËÄÉ²Ă¤·¤̃¤¹¡£\n" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" +"-W, --word-regexp=REGEXP ¥̃¥¯¥í̀¾¤Î¥·¥ó¥¿¥Ă¥¯¥¹¤Ë REGEXP ¤̣ " +" Àµµ¬É½¸½¤È¤·¤ÆÍѤ¤¤̃¤¹¡£\n" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"¥×¥ê¥×¥í¥»¥Ă¥µµ¡Ç½:\n" +" -I, --include=DIRECTORY ¥«¥́¥ó¥È¥Ç¥£¥́¥¯¥È¥ê¤Î¼¡¤Ë¤³¤Î¥Ç¥£¥́¥¯¥È¥ê\n" +" ¤«¤é¥¤¥ó¥¯¥ë¡¼¥É¥Ơ¥¡¥¤¥ë¤̣¥µ¡¼¥Á¤·¤̃¤¹¡£\n" +" -D, --define=NAME[=VALUE] NAME ¤̣ VALUE ¤ËÄêµÁ¤·¤̃¤¹¡£\n" +" (VALUE ¤Ï¾Êά²Äǽ¤Ç¡¢¤³¤Î¾́¹ç¤Ï NAME ¤Ï " +" ¶ơ¤Îʸ»úÎó¤ËÄêµÁ¤µ¤́¤̃¤¹¡£)\n" +" -U, --undefine=NAME NAME ¤ÎÄêµÁ¤̣¼è¤ê¾Ă¤·¤̃¤¹¡£\n" +" -s, --synclines ¹ÔÈÖ¹æ¤È¥Ơ¥¡¥¤¥ë̀¾¤Î¹Ô¤̣À¸À®¤·¤̃¤¹¡£\n" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"¸Â³¦ĂͤΥ³¥ó¥È¥í¡¼¥ë:\n" +" -G, --traditional GNU ÈǤËÆĂͤγÈÄ¥¤̣Í̃À©¤·¤̃¤¹¡£\n" +" -H, --hashsize=PRIME ¥·¥ó¥Ü¥ë¸¡º÷¥Ï¥Ă¥·¥å¥Æ¡¼¥Ö¥ë¤Î¥µ¥¤¥º¤̣\n" +" ¥»¥Ă¥È¤·¤̃¤¹¡£\n" +" -L, --nesting-limit=NUNBER " +"¥̃¥¯¥í¤Î¥Í¥¹¥È²ó¿ô¤Î¾å¸ÂẶͤ¿Í°ÙŪ¤ËÊѹ¹¤·¤̃¤¹¡£\n" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" +"\n" +"Åà·ë¾ơÂ֤ΥƠ¥¡¥¤¥ë: -F, --freeze-state=FILE ºÇ¸å¤Ë»ØÄꤵ¤́¤¿ FILE " +"¤̣Åà·ë¾ơÂ֤ˤ·¤̃¤¹¡£\n" +" -R, --reload-state=FILE ºÇ½é¤Ë»ØÄꤵ¤́¤¿ FILE ¤«¤é\n" +" Åà·ë¤µ¤́¤¿ÄêµÁ¤̣¥í¡¼¥É¤·¤̃¤¹\n" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +" ¥Ç¥Đ¥Ă¥®¥ó¥°:\n" +" -d, --debug=[FLAGS] ¥Ç¥Đ¥Ă¥°¥́¥Ù¥ë¤̣¥»¥Ă¥È¤·¤̃¤¹¡£\n" +" (`aeq' ¤Ï FLAGS ¤Ë´̃¤̃¤́¤̃¤»¤ó¡£)\n" +" -t, --trace=NAME NAME ¤¬ÄêµÁ¤µ¤́¤ë¤È¤½¤́¤̣¥È¥́¡¼¥¹¤·¤̃¤¹¡£\n" +" -l, --arglength=NUM ¥̃¥¯¥í¥È¥́¡¼¥¹¤Î¥µ¥¤¥º¤̣ NUM ¤ËÀ©¸Â¤·¤̃¤¹¡£\n" +" -o, --error-output=FILE ¥Ç¥Đ¥Ă¥°¤È¥È¥́¡¼¥¹¤Î½ĐÎϤ̣ FILE ¤Ë\n" +" ¥ê¥À¥¤¥́¥¯¥È¤·¤̃¤¹¡£\n" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"FLAG ¤Ï°Ê²¼¤Î¤¤¤º¤́¤«¤Ç¤¹:\n" +" t Á´¤Æ¤Î¥̃¥¯¥í¸Æ¤Ó¤À¤·¤̣¥È¥́¡¼¥¹¤·¤̃¤¹\n" +" (traceon ¤Ë¤è¤ë¤â¤Î¤Ë¸ÂÄꤷ¤̃¤»¤ó)\n" +" a ¸½ºß¤Î°ú¿ô¤̣ɽ¼¨¤·¤̃¤¹\n" +" e Ÿ³«¤µ¤́¤¿¤â¤Î¤̣ɽ¼¨¤·¤̃¤¹\n" +" q `a' ¤̃¤¿¤Ï `e' ¤È¶¦¤ËÍѤ¤¡¢É¬Íפ˱₫¤¸¤ÆẶͤ°úÍÑÉä¤Ç°Ï¤ß¤̃¤¹¡£\n" +" c ÄûÀµÁ°¤ÈÄûÀµ¸å¡¢¸Æ½Đ¸å¤Ëɽ¼¨¤·¤̃¤¹\n" +" x ¤½¤Î¥̃¥¯¥í¥³¡¼¥ë¤Ë¸ÇͤΠID ¤̣ÄÉ²Ă¤·¤̃¤¹¡£\n" +" `c' ¤ÈÁȤ߹ç¤ï¤»¤ë¤ÈÊØÍø¤Ç¤¹¡£\n" +" f ¤½¤Î»₫ÅÀ¤ÇÆ₫ÎϤ·¤Æ¤¤¤ë¥Ơ¥¡¥¤¥ë̀¾¤̣ɽ¼¨¤·¤̃¤¹¡£\n" +" l ¤½¤Î»₫ÅÀ¤ÇÆ₫ÎϤ·¤Æ¤¤¤ë¹ÔÈÖ¹æ¤̣ɽ¼¨¤·¤̃¤¹¡£\n" +" p ¥Ñ¥¹¤̣¸¡º÷¤·¤¿·ë²̀¤̣ɽ¼¨¤·¤̃¤¹¡£\n" +" i Æ₫ÎÏ¥Ơ¥¡¥¤¥ë¤ËÀ¸¤¸¤¿ÊѲ½¤̣ɽ¼¨¤·¤̃¤¹¡£\n" +" V ¾åµ¤ÎÁ´¤Æ¤Î FLAG ¤̣»ØÄꤹ¤ë¤³¤È¤̣°Ờ£¤·¤̃¤¹¡£\n" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"FILE ¤¬»ØÄꤵ¤́¤Æ¤¤¤Ê¤¤¾́¹ç¤ª¤è¤Ó»ØÄꤵ¤́¤¿¥Ơ¥¡¥¤¥ë¤¬ `-' ¤Î¾́¹ç¤Ï\n" +" ɸ½àÆ₫ÎϤ¬Æɤ߹₫¤̃¤́¤̃¤¹¡£\n" + +#: src/m4.c:358 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "`%s' ¤ÏÉÔÀµ¤Ê¥Ç¥Đ¥Ă¥°¥ª¥×¥·¥ç¥ó°ú¿ô¤Ç¤¹¡£" + +#: src/m4.c:437 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "ÆâÉô¥¨¥é¡¼¡§¥ª¥×¥·¥ç¥ó¤Î¸å½èÍư¤Ç¡¢ÉÔÀµ¥³¡¼¥É¤¬¸¡½Đ¤µ¤́¤̃¤·¤¿¡£" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô expand_token () Æâ¤Î¥È¡¼¥¯¥ó¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "¥¨¥é¡¼: °ú¿ô¥ê¥¹¥ÈÆâ¤Ë¥Ơ¥¡¥¤¥ë¤Î½ªĂ¼µ¹æ¤¬¤¢¤ê¤̃¤¹¡£" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô expand_argument () ¤Î¥È¡¼¥¯¥ó¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô call_macro () Æâ¤Î¥·¥ó¥Ü¥ë¤Î¼ïÎबÉÔÀµ¤Ç¤¹¡£" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "" +"¥¨¥é¡¼¡§ºÆµ¢ÅªÄêµÁ¤Î¥Í¥¹¥È¤¬»ØÄꤵ¤́¤¿ĂÍ %d ¤̣Ķ¤¨¤Æ¤¤¤̃¤¹¡£\n" +" -L<¿ô»ú> ¥ª¥×¥·¥ç¥ó¤̣ÍѤ¤¤Æ¥Í¥¹¥È¿ô¤Î¾å¸Â¤̣Áư¤ä¤·¤Æ²¼¤µ¤¤¡£" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "¥¨¥é¡¼: divert ¤Î¤¿¤á¤Î¥Æ¥ó¥Ư¥é¥ê¥Ơ¥¡¥¤¥ë¤¬ºîÀ®¤Ç¤¤̃¤»¤ó¡£" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "¥¨¥é¡¼: ¥Æ¥ó¥Ư¥é¥ê¥Ơ¥¡¥¤¥ë¤Ë divert ¤¹¤Ù¤ÆâÍƤ̣ write ¤Ç¤¤̃¤»¤ó¡£" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "¥¨¥é¡¼: Á̃Æ₫¤µ¤́¤ë¤Ù¤¥Ơ¥¡¥¤¥ë¤̣¥³¥Ô¡¼Ăæ¤Ç¤¹¡£" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "¥¨¥é¡¼: Á̃Æ₫¤µ¤́¤ë¤Ù¤¥Ơ¥¡¥¤¥ë¤̣¥ê¡¼¥ÉĂæ¤Ç¤¹¡£" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "" +"divert ¤Î¤¿¤á¤Î¥Ơ¥¡¥¤¥ë¤Î¥¹¥Æ¡¼¥¿¥¹¤̣ÆÀ¤ë¤³¤È¤¬¤Ç¤¤̃¤»¤ó¡£\n" +" (stat ¤Ç¤¤̃¤»¤ó¡£)" + +#: src/path.c:131 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "`%s' ¤È¤¤¤¦¥Ç¥£¥́¥¯¥È¥ê¤«¤é `%s' ¤È¤¤¤¦¥Ơ¥¡¥¤¥ë¤̣¸«¤Ä¤±¤̃¤·¤¿¡£" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "¥ê¥½¡¼¥¹ĂÍ RLIMIT_VMEM ¤̣Ķ¤¨¤Æ¤¤¤̃¤»¤ó¤«¡©\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"¥á¥â¥ê (¥»¥°¥á¥ó¥Æ¡¼¥·¥ç¥ó°ăÈ¿) ¤¬¸¡½Đ¤µ¤́¤̃¤·¤¿¡£\n" +" ¥¹¥¿¥Ă¥¯¤¬¥ª¡¼¥Đ¡¼¥Ơ¥í¡¼¤·¤Æ¤¤¤ë¡¢¤¢¤ë¤¤¤Ï¥Đ¥°¤¬Â¸ºß¤¹¤ë\n" +" ²ÄǽÀ¤¬¤¢¤ê¤̃¤¹¡£" + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". ̀µ¸Â¤ÎºÆµ¢¸Æ¤Ó½Đ¤·¤¬¹Ô¤ï¤́¤Æ¤¤¤Ê¤¤¤«¤É¤¦¤«¥Á¥§¥Ă¥¯¤·¤Æ²¼¤µ¤¤¡£\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "ÆâÉô¥¨¥é¡¼¡§´Ø¿ô symbol_lookup () ¤Ø¤Î°ú¿ô mode ¤¬ÉÔÀµ¤Ç¤¹¡£" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "`%s' ¤ÏÄêµÁ¤µ¤́¤Æ¤¤¤̃¤»¤ó¡£\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "`%s' : %s ¤Ï¡¢ÉÔÀµ¤ÊÀµµ¬É½¸½¤Ç¤¹¡£" + +#~ msgid "%s: option `%s' is ambiguous\n" +#~ msgstr "%s: `%s' ¤ÏÉỒÀÎƤʥª¥×¥·¥ç¥ó̀¾¤Ç¤¹¡£\n" + +#~ msgid "%s: option `--%s' doesn't allow an argument\n" +#~ msgstr "%s: ¥ª¥×¥·¥ç¥ó `--%s' ¤Ï°ú¿ô¤̣¼è¤ë¤³¤È¤¬¤Ç¤¤̃¤»¤ó¡£\n" + +#~ msgid "%s: option `%c%s' doesn't allow an argument\n" +#~ msgstr "%s: ¥ª¥×¥·¥ç¥ó `%c%s' ¤Ï°ú¿ô¤̣¼è¤ë¤³¤È¤¬¤Ç¤¤̃¤»¤ó¡£\n" + +#~ msgid "%s: option `%s' requires an argument\n" +#~ msgstr "%s: ¥ª¥×¥·¥ç¥ó `%s' ¤Ï°ú¿ô¤̣ɬÍפȤ·¤̃¤¹¡£\n" + +#~ msgid "%s: unrecognized option `--%s'\n" +#~ msgstr "%s: --%s ¤Ïǧ¼±¤µ¤́¤Ê¤¤¥ª¥×¥·¥ç¥ó¤Ç¤¹¡£\n" + +#~ msgid "%s: unrecognized option `%c%s'\n" +#~ msgstr "%s: %c%s ¤Ïǧ¼±¤µ¤́¤Ê¤¤¥ª¥×¥·¥ç¥ó¤Ç¤¹¡£\n" + +#~ msgid "%s: illegal option -- %c\n" +#~ msgstr "%s: %c ¤ÏÉÔÀµ¥ª¥×¥·¥ç¥ó¤Ç¤¹¡£\n" + +#~ msgid "%s: invalid option -- %c\n" +#~ msgstr "%s: %c ¤Ï̀µ¸ú¤Ê¥ª¥×¥·¥ç¥ó¤Ç¤¹¡£\n" + +#~ msgid "%s: option requires an argument -- %c\n" +#~ msgstr "%s: %c ¥ª¥×¥·¥ç¥ó¤Ë¤Ï°ú¿ô¤¬É¬ÍפǤ¹¡£\n" + +#~ msgid "No previous regular expression" +#~ msgstr "Àµµ¬É½¸½¤¬ÄêµÁ¤µ¤́¤Æ¤¤¤̃¤»¤ó¡£" + +#~ msgid "Memory exhausted" +#~ msgstr "¥á¥â¥ê¤¬»Ä¤Ă¤Æ¤¤¤̃¤»¤ó¡£" diff --git a/po/m4.pot b/po/m4.pot new file mode 100644 index 00000000..75077ee6 --- /dev/null +++ b/po/m4.pot @@ -0,0 +1,116 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 1997-10-06 07:30+0159\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: ENCODING\n" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" + +#: src/m4.c:355 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "" + +#: src/m4.c:434 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "" diff --git a/po/nl.gmo b/po/nl.gmo Binary files differnew file mode 100644 index 00000000..1452272f --- /dev/null +++ b/po/nl.gmo diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 00000000..fd69a4ff --- /dev/null +++ b/po/nl.po @@ -0,0 +1,464 @@ +# Dutch messages for GNU m4. +# Copyright (C) 1998 Free Software Foundation, Inc. +# Erick Branderhorst <Erick.Branderhorst@asml.nl>, 1998. +# +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4d\n" +"POT-Creation-Date: 1998-05-25 12:26+0200\n" +"PO-Revision-Date: 1998-05-23 09:27+02:00\n" +"Last-Translator: Erick Branderhorst <Erick.Branderhorst@asml.nl>\n" +"Language-Team: dutch <nl@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:272 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Let op: Te weinig argument voor ingebouwde functie `%s'" + +#: src/builtin.c:278 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "" +"Let op: Overbodige argumenten voor ingebouwde functie `%s' worden genegeerd" + +#: src/builtin.c:298 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Niet numeriek argument voor ingebouwde functie `%s'" + +#: src/builtin.c:438 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "INTERNE FOUT: Onjuist teken data type in define_macro ()" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, c-format +msgid "Undefined name %s" +msgstr "Ongedefinieerde naam %s" + +#: src/builtin.c:636 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "INTERNE FOUT: Ingebouwde functie niet gevonden in functie tabel!" + +#: src/builtin.c:644 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "INTERNE FOUT: Onjuist teken data type in m4_dumpdef ()" + +#: src/builtin.c:695 +#, c-format +msgid "Undefined macro `%s'" +msgstr "Ongedefinieerde macro `%s'" + +#: src/builtin.c:735 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "INTERNE FOUT: Onjuist symbool type in m4_defn ()" + +#: src/builtin.c:772 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Kan geen pijp openen voor commando `%s'" + +#: src/builtin.c:811 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Radix in evaluatie buiten bereik (radix = %d)" + +#: src/builtin.c:820 +msgid "Negative width to eval" +msgstr "Negatieve breedte te evalueren" + +#: src/builtin.c:925 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "Niet numeriek argument voor %s" + +#: src/builtin.c:937 +#, c-format +msgid "Cannot undivert %s" +msgstr "Cannot undivert %s" + +#: src/builtin.c:1043 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "Kan %s niet openen" + +#: src/builtin.c:1248 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Debugmode: onjuiste debug vlaggen: `%s'" + +#: src/builtin.c:1284 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Kan fout bestand niet instellen: %s" + +#: src/builtin.c:1501 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "LET OP: \\0 zal verdwijnen, gebruik hiervoor \\& als vervanging" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "Onjuiste reguliere expressie `%s': %s" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "Fout overeenkomen reguliere expressies `%s'" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"INTERNE FOUT: Ingebouwde functie niet gevonden in functie tabel! (trace_pre " +"())" + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "INTERNE FOUT: Onjuiste teken data type (trace_pre ())" + +#: src/eval.c:277 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "Onjuiste expressie in evaluatie (ontbrekend rechter haakje): %s" + +#: src/eval.c:283 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "Onjuist expressie in evaluatie: %s" + +#: src/eval.c:288 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "Onjuist expressie in evaluatie (onjuiste invoer): %s" + +#: src/eval.c:293 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "Onjuist expressie in evaluatie (te veel invoer): %s" + +#: src/eval.c:298 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "Delen door nul in evaluatie: %s" + +#: src/eval.c:303 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Modulo door nul in evaluatie: %s" + +#: src/eval.c:308 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "INTERNE FOUT: Onjuiste fout code in evaluate ()" + +#: src/eval.c:547 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "INTERNE FOUT: Onjuiste vergelijkings operator in cmp_term ()" + +#: src/eval.c:590 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "INTERNE FOUT: Onjuiste schuif operator in shift_term ()" + +#: src/eval.c:674 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "INTERNE FOUT: Onjuiste operator in mult_term ()" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "INTERNE FOUT: Ingebouwde functie niet gevonden in functie tabel!" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "INTERNE FOUT: Onjuist teken data type in freeze_one_symbol ()" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "Verwacht nieuwe regel in gefixeerd bestand" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Verwacht karakter `%c' in gefixeerd bestand" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "Slecht geformateerd gefixeerd bestand" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "Voorbarig einde van gefixeerd bestand" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "`%s' van gefixeerd bestand niet gevonden in functie tabel!" + +#: src/input.c:174 +#, c-format +msgid "Input read from %s" +msgstr "Invoer gelezen vanuit %s" + +#: src/input.c:231 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "INTERNE FOUT: Recursieve push_string!" + +#: src/input.c:311 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Invoer reverted naar %s, lijn %d" + +#: src/input.c:325 +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "INTERNE FOUT: Invoer stapel botch in pop_input ()" + +#: src/input.c:364 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "INTERNE FOUT: Onjuiste aanroep naar init_macro_token ()" + +#: src/input.c:413 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "INTERNE FOUT: Invoer stapel botch in peek_input ()" + +#: src/input.c:470 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "INTERNE FOUT: Invoer stapel botch in next_char ()" + +#: src/input.c:550 +msgid "NONE" +msgstr "GEEN" + +#: src/input.c:777 +msgid "ERROR: EOF in string" +msgstr "FOUT: Einde van bestand teken in string" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "FOUT: Stapel overflow. (Infinite define recursion?)" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Probeer `%s --help' voor meer informatie.\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "Gebruik: %s [OPTIE]... [BESTAND]...\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Verplichte of optionele argumenten voor lange opties zijn ook verplicht of\n" +"optioneel voor korte opties.\n" +"\n" +"Operatie modi:\n" +" --help toon help tekst en beëindig programma\n" +" --version toon versie informatie en beeindig programma\n" +" -e, --interactive unbuffer output, negeer interrupts\n" +" -E, --fatal-warnings stop uitvoering na eerste waarschuwing\n" +" -Q, --quiet, --silent onderdruk sommige waarschuwingen voor\n" +" ingebouwde functies\n" +" -P, --prefix-builtins forceer een `m4_' voorvoegsel voor alle \n" +" ingebouwde functies\n" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr " -W, --word-regexp=REGEXP gebruik REGEXP voor macro naam syntax\n" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"Voorbewerkings features:\n" +" -I, --include=DIRECTORY zoek in tweede instantie in deze directory " +"voor\n" +" inclusies\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME verwijder ingebouwde functie NAME\n" +" -s, --synclines genereer `#line NO \"FILE\"' regel\n" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"Limieten controlle:\n" +" -G, --traditional onderdruk alle GNU uitbreidingen\n" +" -H, --hashsize=PRIME stel symbolen opzoek hash tabel grootte\n" +" -L, --nesting-limit=NUMBER verander kunstmatige nesting limiet\n" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" +"\n" +"Gefixeerd staat bestanden:\n" +" -F, --freeze-state=FILE produceerd een gefixeerd staat van BESTAND\n" +" aan het einde\n" +" -R, --reload-state=FILE herlaad een gefixeerde staat van BESTAND\n" +" aan het begin\n" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Debugging:\n" +" -d, --debug=[VLAGGEN] stel debug nivo in (geen VLAGGEN \n" +" impliceert `aeq')\n" +" -t, --trace=NAAM traceer NAAM wanneer het wordt gedefinieerd\n" +" -l, --arglength=NUM restrict macro traceer grootte\n" +" -o, --error-output=FILE redirect debug en traceer uitvoer\n" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"Als geen BESTAND of als BESTAND `-' is, standaard invoer wordt gelezen.\n" + +#: src/m4.c:355 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "Onjuiste debug vlaggen: `%s'" + +#: src/m4.c:434 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "INTERNE FOUT: Onjuiste code in afgeleide argumenten" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "INTERNE FOUT: Onjuist teken type in expand_token ()" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "FOUT: Einde van bestand teken in argumentenlijst" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "INTERNE FOUT: Onjuist teken type in expand_argument ()" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "INTERNE FOUT: Onjuist symbool type in call_macro ()" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "" +"FOUT: Recursie limiet of %d overschreden, gebruik -L<N> om dit te wijzigen" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "FOUT: Kan geen tijdelijk bestand aanmaken voor diversion" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "FOUT: Kan diversion niet flushen naar tijdelijk bestand" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "FOUT: Kopieren ingevoegde bestanden" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "FOUT: Lezen ingevoegd bestand" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "Cannot stat diversion" + +#: src/path.c:131 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "Zoeken naar `%s' via PATH levert `%s'" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "VMEM limiet overschreden?\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Geheugen bounds violation gedetecteerd (SIGSEGV). Een stack overflow \n" +"is opgetreden, of er is een fout in " + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". Kontroleer voor mogelijk oneindige recusie.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "INTERNE FOUT: Ongeldige mode voor symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Naam `%s' is niet bekend\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "Onjuiste reguliere expressie: `%s': %s" diff --git a/po/pl.gmo b/po/pl.gmo Binary files differnew file mode 100644 index 00000000..4bb38992 --- /dev/null +++ b/po/pl.gmo diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 00000000..8cdf9481 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,500 @@ +# Polish translations for the GNU m4 messages. +# Copyright (C) 1998 Free Software Foundation, Inc. +# Rafa³ Maszkowski <rzm@icm.edu.pl>, 1998. +# +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4.3\n" +"POT-Creation-Date: 1998-10-04 01:31+0200\n" +"PO-Revision-Date: 1998-08-05 17:30+0200\n" +"Last-Translator: Rafa³ Maszkowski <rzm@icm.edu.pl>\n" +"Language-Team: Polish <pl@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-2\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:317 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Uwaga: Za ma³o argumentów dla wbodowanego `%s'" + +#: src/builtin.c:323 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "Uwaga: Nadmiarowe argumenty do built-in `%s' zosta³y zignorowane" + +#: src/builtin.c:351 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Nienumeryczny argument do built-in `%s'" + +#: src/builtin.c:450 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "B£¡D WEWNÊTRZNY: Z³y typ danych tokenu w define_macro ()" + +#: src/builtin.c:645 src/builtin.c:708 src/builtin.c:1331 src/builtin.c:1355 +#, c-format +msgid "Undefined name %s" +msgstr "Niezdefiniowana nazwa %s" + +#: src/builtin.c:673 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "B£¡D WEWNÊTRZNY: Wbudowane nie znalezione w tablicy wbudowanych!" + +#: src/builtin.c:681 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "B£¡D WEWNÊTRZNY: Z³y typ danych tokenu w m4_dumpref ()" + +#: src/builtin.c:732 +#, c-format +msgid "Undefined macro `%s'" +msgstr "Niezdefiniowane makro `%s'" + +#: src/builtin.c:772 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "B£¡D WEWNETRZNY: Z³y typ symbolu w m4_defn ()" + +#: src/builtin.c:838 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Nie mogê otworzyæ potoku do komendy `%s'" + +#: src/builtin.c:875 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Baza w eval poza zakresem (radix = %d)" + +#: src/builtin.c:884 +msgid "Negative width to eval" +msgstr "Ujemna d³ugo¶æ w eval" + +#: src/builtin.c:976 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "Nienumeryczny argument dla %s" + +#: src/builtin.c:988 +#, c-format +msgid "Cannot undivert %s" +msgstr "Nie mogê przetowrzyæ z powrotem %s" + +#: src/builtin.c:1132 +#, fuzzy, c-format +msgid "Undefined syntax code %c" +msgstr "Niezdefiniowana nazwa %s" + +#: src/builtin.c:1182 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "Nie mogê otworzyæ %s" + +#: src/builtin.c:1391 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Tryb debugowania: z³e flagi debugowania: `%s'" + +#: src/builtin.c:1427 +#, c-format +msgid "Cannot set error file: %s" +msgstr "Nie mogê ustawiæ pliku b³êdów: %s" + +#: src/builtin.c:1644 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "UWAGA: \\0 zniknie, w podstawieniach u¿yj zamiast tego \\&" + +#: src/builtin.c:1705 src/builtin.c:1765 src/input.c:979 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "B³êdne wyra¿enie regularne `%s': %s" + +#: src/builtin.c:1716 src/builtin.c:1789 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "B³±d dopasowania do wyra¿enia regularnego `%s'" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "" +"B£¡D WEWNÊTRZNY: Wbudowane nie znalezione w tablicy wbudowanych! (trace_pre " +"())" + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "B£¡D WEWNÊTRZNY: Z³y typ danych tokenu (trace_pre ())" + +#: src/eval.c:297 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "B³êdne wyra¿enie w eval (brakuj±cy prawy nawias): %s" + +#: src/eval.c:303 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "B³êdne wyra¿enie w eval: %s" + +#: src/eval.c:308 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "B³êdne wyra¿enie w eval (z³e dane wej¶ciowe): %s" + +#: src/eval.c:313 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "B³êdne wyra¿enie w eval (nadmiarowe dane): %s" + +#: src/eval.c:318 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "Dzielenie przez zero w eval: %s" + +#: src/eval.c:323 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Modulo zero w eval: %s" + +#: src/eval.c:328 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny kod b³êdu w evaluate ()" + +#: src/eval.c:582 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny operator porównania w cmp_term ()" + +#: src/eval.c:627 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny operator przesuniêcia w shift_term ()" + +#: src/eval.c:726 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny opertaotr w mult_term ()" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "B£¡D WEWNÊTRZNY: Wbudowane nie znalezione w tablicy wbudowanych!" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny typ danych tokenu w freeze_one_symbol ()" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "Oczekiwany line fedd w pliku zamro¿onym" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Oczekiwany znak `%c' w pliku zamro¿onym" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "¬le sformatowy plik zamro¿ony" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "Przedwczesny koniec pliku zamro¿onego" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "`%s' z pliku zamro¿onego nie znalezione w tablicy wbudowanych!" + +#: src/input.c:306 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "Dane wej¶ciowe wycofane do %s, linia %d" + +#: src/input.c:334 +#, c-format +msgid "Input read from %s" +msgstr "Dane wej¶ciowe przeczytane z %s" + +#: src/input.c:494 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "B£¡D WEWNÊTRZNY: Rekursywny push_string!" + +#: src/input.c:611 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdne wywo³anie init_macro_token ()" + +#: src/input.c:651 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "B£¡D WEWNÊTRZNY: B³±d stosu wej¶ciowego w next_char ()" + +#: src/input.c:688 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "B£¡D WEWNÊTRZNY: B³±d stosu wej¶ciowego w peek_input ()" + +#: src/input.c:791 +msgid "NONE" +msgstr "¯ADEN" + +#: src/input.c:1130 src/input.c:1157 +msgid "ERROR: EOF in string" +msgstr "B£¡D: EOF w ³añcuchu" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "B£¡D: Przepe³nienie stosu. (Nieskoñczona rekursja definicji?)" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Spróbuj `%s --help' ¿eby dowiedzieæ siê wiêcej.\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "U¿ycie: %s [OPCJA]... [PLIK]...\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Argumenty obowi±zkowe lub opcjonalne dla opcji d³ugich s± obowi±zkowe lub\n" +"opcjonalne równie¿ dla krótkich.\n" +"\n" +"Tryby pracy:\n" +" --help wy¶wietl ten opis i zakoñcz\n" +" --version wy¶wietl informacjê o wersji i zakoñcz\n" +" -e, --intercative nie buforuj wyj¶cia, ignoruj przerwania\n" +" -E, --fatal-warnings zatrzymaj siê po pierwszym ostrz¿eniu\n" +" -Q, --quiet, --silent nie pokazuj niektórych ostrze¿eñ dla " +"wbudowanych\n" +" -P, --prefix-builtins dodaj zawsze `m4_' przez wszystkimi " +"wbudowanymi\n" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr " -W, --word-regexp=WYR_REGUL u¿yj WYR_REGUL w sk³adni nazw makr\n" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"W³a¶ciwo¶ci preprocesora:\n" +" -I, --include=KATALOG szukaj includes w tym KATALOGu\n" +" -D, --define=NAZWA[=WARTO¦Æ] wprowad¼ NAZWÊ z WARTO¦CI¡ lub pust±\n" +" -U, --undefine=NAZWA skasuj wbudowan± NAZWÊ\n" +" -s, --synclines generuj linie `#line NR \"PLIK\"\n" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"Sterowanie ograniczeniami:\n" +" -G, --traditional wy³±cz wszystkie rozszrzenia GNU\n" +" -H, --hashzize=PIERWSZA ustaw rozmiar tablicy mieszaj±cej dla " +"symboli\n" +" -L, --nesting-limit=LICZBA zmieñ sztuczny limit zag³ebieñ\n" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" +"\n" +"Zamro¿one pliki stanu:\n" +" -F, --freeze-state=PLIK zapisz zamro¿ony PLIK stanu na koñcu\n" +" -R, --reload-state=PLIK za³aduj zamro¿ony PLIK stanu na pocz±tku\n" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Debugowanie:\n" +" -d, --debug=[FLAGI] ustaw poziom debugowania (bez FLAG: `aeg')\n" +" -t, --trace=NAZWA ¶led¼ NAZWÊ, kiedy bêdzie zdefiniowana\n" +" -l, --arglength=ILE ogranicz rozmiar ¶ledzenia makr\n" +" -o, --error-output=PLIK przekieruj wyniki debugowania i ¶ledzenia\n" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"FLAGI mog± byæ nastêpuj±ce:\n" +" t ¶led¼ wszystkie wywo³ania makr, nie tylko te z traceon\n" +" a poka¿ w³a¶ciwe argumenty\n" +" e poka¿ rozwiniêcie\n" +" q zabezpiecz znaki specjalne, z flag± a lub e\n" +" c poka¿ przez zebraniem, po zebraniu i po wywo³aniu\n" +" x dodaj unikalny identfikator wywo³ania makra, po¿yteczne z flag± c\n" +" f podaj nazwê bie¿±cego pliku wej¶ciowego\n" +" l podaj numer bie¿±cej linii\n" +" p poka¿ wyniki przeszukiwañ ¶cie¿ek\n" +" i poka¿ zmiany plików wej¶ciowych\n" +" V skrót do wszystkich powy¿szych flag\n" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"Je¿eli brak PLIKu lub PLIK to `-', czytane jest std. wej¶cie.\n" + +#: src/m4.c:365 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "B³êdne flagi debugowania: `%s'" + +#: src/m4.c:444 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "B£¡D WEWNÊTRZNY: B³êdny kod w od³o¿onych argumentach" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny typ tokena w expand_token ()" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "B£¡D: EOF w li¶cie argumentów" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny typ tokena w expand_argument ()" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "B£¡D WEWNÊTRZNY: B³êdny symbol w call_macro ()" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "B£¡D: Osi±gniêty limit rekursji %d, u¿yj -L<N> ¿eby go zmieniæ" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "B£¡D: Nie mogê utworzyæ plików tymczasowych dla przetwarzania" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "B£¡D: Nie mogê zapisac zmian przetwarzania do pliku tymczasowego" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "B£¡D: Kopiowanie w³o¿onego pliku" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "B£¡D: Czytanie w³o¿onego pliku" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "Nie mogê zrobiæ stat na danych przetwarzanych" + +#: src/path.c:162 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "Przeszukanie ¶cie¿ki dla `%s' znalaz³o `%s'" + +#: src/path.c:239 +#, fuzzy, c-format +msgid "Module search for `%s' found `%s'" +msgstr "Przeszukanie ¶cie¿ki dla `%s' znalaz³o `%s'" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "przekroczony limit VMEM\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Wykryto pogwa³cenie ograniczeñ adresów pamiêci (SIGSEGV). Albo dosz³o do\n" +"przepe³nienia stosu albo jest b³±d w " + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". Sprawd¼ czy nie dosz³o do nieskoñczonej rekursji.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "B£¡D WEWNÊTRZNY: Nielegalny tryb w symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "Nazwa `%s' jest nieznana\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "Z³e wyra¿enie regularne: `%s': %s" + +#~ msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +#~ msgstr "B£¡D WEWNÊTRZNY: B³±d stosu wej¶ciowego w pop_input ()" + +#~ msgid "%s: option `%s' is ambiguous\n" +#~ msgstr "%s: opcja `%s' jest niejednoznaczna\n" + +#~ msgid "%s: option `--%s' doesn't allow an argument\n" +#~ msgstr "%s: opcja `--%s' nie mo¿e mieæ argumentu\n" + +#~ msgid "%s: option `%c%s' doesn't allow an argument\n" +#~ msgstr "%s: opcja `%c%s' nie mo¿e mieæ argumentu\n" + +#~ msgid "%s: option `%s' requires an argument\n" +#~ msgstr "%s: opcja `%s' wymaga argumentu\n" + +#~ msgid "%s: unrecognized option `--%s'\n" +#~ msgstr "%s: nierozpoznana opcja --%s'\n" + +#~ msgid "%s: unrecognized option `%c%s'\n" +#~ msgstr "%s: nierozpoznana opcja %c%s'\n" + +#~ msgid "%s: illegal option -- %c\n" +#~ msgstr "%s: nielegalna opcja -- %c\n" + +#~ msgid "%s: invalid option -- %c\n" +#~ msgstr "%s: b³êdna opcja -- %c\n" + +#~ msgid "%s: option requires an argument -- %c\n" +#~ msgstr "%s: opcja wymaga argumentu -- %c\n" + +#~ msgid "No previous regular expression" +#~ msgstr "Brak uprzedniego wyra¿enia regularnego" + +#~ msgid "Memory exhausted" +#~ msgstr "Pamiêæ wyczerpana" diff --git a/po/ru.gmo b/po/ru.gmo Binary files differnew file mode 100644 index 00000000..bd27331a --- /dev/null +++ b/po/ru.gmo diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 00000000..1f847158 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,498 @@ +# ́ÏËÁ̀ÉÚÁĂÉÑ m4-1.4.3 +# Copyright (C) 1997 Free Software Foundation, Inc. +# Denis Y. Pershin <dyp@siblug.org>, 1997. +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4.3\n" +"POT-Creation-Date: 1998-08-03 17:14+0200\n" +"PO-Revision-Date: 1997-07-12 20:58\n" +"Last-Translator: Denis Y. Pershin <dyp@siblug.org>\n" +"Language-Team: Russian <ru@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=koi8-r\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:272 +#, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "đ̉ÅÄƠĐ̉ÅÖÄÅÎÉÅ: ó̀ÉÛËÏÍ ÍÁ̀Ï Á̉ÇƠÍÅÎÔÏ× Ä̀Ñ ×ÓỔÏÅÎÎÏÊ ̀ÅËÓÅÍÙ '%s'" + +#: src/builtin.c:278 +#, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "" +"đ̉ÅÄƠĐ̉ÅÖÄÅÎÉÅ: éÚÂÙÔÏ̃ÎÙÅ Á̉ÇƠÍÅÎÔÙ Ä̀Ñ ×ÓỔÏÅÎÎÏÊ ̀ÅËÓÅÍÙ '%s' " +"Đ̉ÏÉÇÎÏ̉É̉Ï×ÁÎÙ" + +#: src/builtin.c:298 +#, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "îÅ ̃ÉÓ̀Ï×ÏÊ Á̉ÇƠÍÅÎÔ Ä̀Ñ ×ÓỔÏÅÎÎÏÊ ̀ÅËÓÅÍÙ '%s'" + +#: src/builtin.c:438 +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ̀ÅËÓÅÍÙ × define_macro ()" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, c-format +msgid "Undefined name %s" +msgstr "éÍÑ %s ÎÅÏĐ̉ÅÄÅ̀ÅÎÏ" + +#: src/builtin.c:636 +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "÷îơộåîîññ ïûéâëá: ÷ÓỔÏÅÎÎÁÑ ̀ÅËÓÅÍÁ ÎÅ ÎÁÊÄÅÎÁ!" + +#: src/builtin.c:644 +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ̀ÅËÓÅÍÙ × m4_dumpdef ()" + +#: src/builtin.c:695 +#, c-format +msgid "Undefined macro `%s'" +msgstr "îÅÏĐ̉ÅÄÅ̀ÅÎÎÙÊ ÍÁË̉ÏÓ '%s'" + +#: src/builtin.c:735 +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ÓÉÍ×Ï̀Á × m4_defn ()" + +#: src/builtin.c:772 +#, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔË̉ÙÔØ ËÁÎÁ̀ Ä̀Ñ ËÏÍÍÁÎÄÙ '%s'" + +#: src/builtin.c:811 +#, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "̣ÁÄÉËÓ × ×Ù̉ÁÖÅÎÉÉ ×ÙÈÏÄÉÔ ÚÁ Đ̉ÅÄÅ̀Ù (radix = %d)" + +#: src/builtin.c:820 +msgid "Negative width to eval" +msgstr "ïỔÉĂÁÔÅ̀ØÎÁÑ ÛÉ̉ÉÎÁ" + +#: src/builtin.c:925 +#, c-format +msgid "Non-numeric argument to %s" +msgstr "îÅ ̃ÉÓ̀Ï×ÏÊ Á̉ÇƠÍÅÎÔ Ä̀Ñ %s" + +#: src/builtin.c:937 +#, c-format +msgid "Cannot undivert %s" +msgstr "îÅ×ÏÚÍÏÖÎÏ ×Å̉ÎƠÔØ ×Ù×ÏÄ ÉÚ %s" + +#: src/builtin.c:1043 src/freeze.c:207 +#, c-format +msgid "Cannot open %s" +msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔË̉ÙÔØ %s" + +#: src/builtin.c:1248 +#, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "̣ÅÖÉÍ ÏỒÁÄËÉ: ÎÅ×Å̉ÎÙÊ Æ̀ÁÇ ÏỒÁÄËÉ: '%s'" + +#: src/builtin.c:1284 +#, c-format +msgid "Cannot set error file: %s" +msgstr "îÅ×ÏÚÍÏÖÎÏ ÎÁÚÎÁ̃ÉÔØ ÆÁỀ ÏÛÉÂÏË %s" + +#: src/builtin.c:1501 +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "đ̣åäơđ̣åöäåîéå: \\0 ÉÓ̃ÅÚÎÅÔ, ÉÓĐÏ̀ØÚƠÊÔÅ \\& × ÚÁÍÅÎÁÈ" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, c-format +msgid "Bad regular expression `%s': %s" +msgstr "îÅ×Å̉ÎÏÅ ̉ÅÇỜÑ̉ÎÏÅ ×Ù̉ÁÖÅÎÉÅ: '%s': %s" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, c-format +msgid "Error matching regular expression `%s'" +msgstr "ïÛÉÂËÁ ÓÏĐÏÓÔÁ×̀ÅÎÉÑ ̉ÅÇỜÑ̉ÎÏÇÏ ×Ù̉ÁÖÅÎÉÑ '%s'" + +#: src/debug.c:379 +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "÷îơộåîîññ ïûéâëá: ÷ÓỔÏÅÎÎÁÑ ̀ÅËÓÅÍÁ ÎÅ ÎÁÊÄÅÎÁ! (trace_pre ())" + +#: src/debug.c:387 +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ̀ÅËÓÅÍÙ (trace_pre ())" + +#: src/eval.c:277 +#, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "îÅ×Å̉ÎÏÅ ×Ù̉ÁÖÅÎÉÅ (ÏÔÓƠÔÓÔ×ƠÅÔ Đ̉Á×ÙÅ ÓËÏÂËÉ): %s" + +#: src/eval.c:283 +#, c-format +msgid "Bad expression in eval: %s" +msgstr "îÅ×Å̉ÎÏÅ ×Ù̉ÁÖÅÎÉÅ: %s" + +#: src/eval.c:288 +#, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "îÅ×Å̉ÎÏÅ ×Ù̉ÁÖÅÎÉÅ (bad input): %s" + +#: src/eval.c:293 +#, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "îÅ×Å̉ÎÏÅ ×Ù̉ÁÖÅÎÉÅ (excess input): %s" + +#: src/eval.c:298 +#, c-format +msgid "Divide by zero in eval: %s" +msgstr "äÅ̀ÅÎÉÅ ÎÁ ÎÏ̀Ø × ×Ù̉ÁÖÅÎÉÉ: %s" + +#: src/eval.c:303 +#, c-format +msgid "Modulo by zero in eval: %s" +msgstr "íÏÄỜØÎÏÅ ÄÅ̀ÅÎÉÅ ÎÁ ÎÏ̀Ø × ×Ù̉ÁÖÅÎÉÉ: %s" + +#: src/eval.c:308 +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ËÏÄ ÏÛÉÂËÉ × evaluate ()" + +#: src/eval.c:547 +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÏÅ Ó̉Á×ÎÅÎÉÅ × cmp_term ()" + +#: src/eval.c:590 +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÏĐÅ̉ÁÔÏ̉ ÓÄ×ÉÇÁ × shift_term ()" + +#: src/eval.c:674 +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÏĐÅ̉ÁÔÏ̉ × mult_term ()" + +#: src/freeze.c:115 +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "÷îơộåîîññ ïûéâëá: ÷ÓỔÏÅÎÎÁÑ ̀ÅËÓÅÍÁ ÎÅ ÎÁÊÄÅÎÁ!" + +#: src/freeze.c:128 +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ̀ÅËÓÅÍÙ × freeze_one_symbol ()" + +#: src/freeze.c:159 +msgid "Expecting line feed in frozen file" +msgstr "ïÖÉÄÁÅÔÓÑ ĐÅ̉Å×ÏÄ ÓỔÏËÉ × ÆÁỀÅ-ÏẨÁÚÅ ĐÁÍÑÔÉ" + +#: src/freeze.c:161 +#, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "ïÖÉÄÁÅÔÓÑ ÓÉÍ×Ï̀ '%c' × ÆÁỀÅ-ÏẨÁÚÅ ĐÁÍÑÔÉ" + +#: src/freeze.c:218 +msgid "Ill-formated frozen file" +msgstr "îÅ×Å̉ÎÙÊ ÆÏ̉ÍÁÔ ÆÁỀÁ-ÏẨÁÚÁ ĐÁÍÑÔÉ" + +#: src/freeze.c:273 src/freeze.c:289 +msgid "Premature end of frozen file" +msgstr "đ̉ÅÖÄÅ×̉ÅÍÅÎÎÙÊ ËÏÎÅĂ ÆÁỀÁ-ÏẨÁÚÁ ĐÁÍÑÔÉ" + +#: src/freeze.c:323 +#, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "'%s' ÉÚ ÆÁỀÁ-ÏẨÁÚÁ ĐÁÍÑÔÉ ÎÅ ÎÁÊÄÅÎÁ ×Ï ×ÓỔÏÅÎÎÏÊ ÔÁẦÉĂÅ!" + +#: src/input.c:174 +#, c-format +msgid "Input read from %s" +msgstr "÷×ÏÄ ÉÚ %s" + +#: src/input.c:231 +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "÷îơộåîîññ ïûéâëá: ̣ÅËỞÓÉ×ÎÁÑ push_string!" + +#: src/input.c:311 +#, c-format +msgid "Input reverted to %s, line %d" +msgstr "÷×ÏÄ ĐÅ̉ÅÎÁĐ̉Á×̀ÅÎ × %s , ÓỔÏËÁ %d" + +#: src/input.c:325 +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "÷îơộåîîññ ïûéâëá: ïÛÉÂËÁ ×ÈÏÄÎÏÇÏ ÓÔÅËÁ × pop_input ()" + +#: src/input.c:364 +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ×ÙÚÏ× init_macro_token ()" + +#: src/input.c:413 +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "÷îơộåîîññ ïûéâëá: ïÛÉÂËÁ ×ÈÏÄÎÏÇÏ ÓÔÅËÁ × peek_input ()" + +#: src/input.c:470 +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "÷îơộåîîññ ïûéâëá: ïÛÉÂËÁ ×ÈÏÄÎÏÇÏ ÓÔÅËÁ × next_char ()" + +#: src/input.c:550 +msgid "NONE" +msgstr "îé₫åçï" + +#: src/input.c:777 +msgid "ERROR: EOF in string" +msgstr "ïûéâëá: ëÏÎÅĂ ÆÁỀÁ × ÓỔÏËÅ" + +#: src/m4.c:106 +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "ïûéâëá: đÅ̉ÅĐÏ̀ÎÅÎÉÅ ÓÔÅËÁ. (âÅÓËÏÎÅ̃ÎÏÅ ̉ÅËỞÓÉ×ÎÏÅ ÏĐ̉ÅÄÅ̀ÅÎÉÅ?)" + +#: src/m4.c:133 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "đÏĐ̉ÏÂƠÊÔÅ '%s --help' Ä̀Ñ ÉÎÆÏ̉ÍÁĂÉÉ.\n" + +#: src/m4.c:137 +#, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "éÓĐÏ̀ØÚÏ×ÁÎÉÅ: %s [OPTION]... [FILE]...\n" + +#: src/m4.c:138 +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"ïÂÑÚÁÔÅ̀ØÎÙÅ É̀É ÎÅÏÂÑÚÁÔÅ̀ØÎÙÅ Á̉ÇƠÍÅÎÔÙ Ä̀Ñ Ä̀ÉÎÎÙÈ ÏĐĂÉÉ ÔÁËÏ×Ù É Ä̀Ñ " +"ËÏ̉ÏÔËÉÈ\n" +"\n" +"̣ÅÖÉÍÙ ̉ÁÂÏÔÙ:\n" +" --help ĐÏËÁÚÁÔØ ĐÏÍÏƯØ É ×ÙÊÔÉ\n" +" --version ×Ù×ÅÓÔÉ ÉÎÆÏ̉ÍÁĂÉÀ Ï ×Å̉ÓÉÉ É ×ÙÊÔÉ\n" +" -e, --interactive ÎÅÂƠÆÅ̉ÉÚÏ×ÁÎÎÙÊ ×Ù×ÏÄ, ÉÇÎÏ̉É̉Ï×ÁÔØ " +"Đ̉Å̉Ù×ÁÎÉÑ\n" +" -E, --fatal-warnings ÏÓÔÁÎÏ×ÉÔØÓÑ ĐÏÓ̀Å ĐÅ̉×ÏÇÏ Đ̉ÅÄƠĐ̉ÅÖÄÅÎÉÑ\n" +" -Q, --quiet, --silent ĐÏÄÁ×̀ÑÔØ Đ̉ÅÄƠĐ̉ÅÖÄÅÎÉÑ Ä̀Ñ ×ÓỔÏÅÎÎÙÈ " +"ÆƠÎËĂÉÊ\n" +" -P, --prefix-builtins ÄÏÂÁ×̀ÑÔØ Đ̉ÅÆÉËÓ `m4_' Ä̀Ñ ×ÓÅÈ ×ÓỔÏÅÎÎÙÈ " +"ÆƠÎËĂÉÊ\n" + +#: src/m4.c:151 +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr "" +" -W, --word-regexp=REGEXP ÉÓĐÏ̀ØÚÏ×ÁÔØ REGEXP Ä̀Ñ ÓÉÎÔÁËÓÉÓÁ ÉÍÅÎ " +"ÍÁË̉ÏÓÏ×\n" + +#: src/m4.c:155 +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"ïĐĂÉÉ Đ̉ÅĐ̉ÏĂÅÓÓÏ̉Á:\n" +" -I, --include=DIRECTORY ÉÓËÁÔØ × ĐÏÄËÁÔÁ̀ÏÇÅ ×Ë̀À̃ÁÅÍÙÅ ÆÁỀÙ\n" +" -D, --define=NAME[=VALUE] ÏĐ̉ÅÄÅ̀ÉÔØ, ̃ÔÏ NAME ÉÍÅÅÔ VALUE, É̀É ĐƠÓÔ\n" +" -U, --undefine=NAME ƠÄÁ̀ÉÔØ ×ÓỔÏÅÎÎƠÀ ÆƠÎËĂÉÀ NAME\n" +" -s, --synclines ÇÅÎÅ̉É̉Ï×ÁÔØ ÓỔÏËÉ `#line NO \"FILE\"'\n" + +#: src/m4.c:163 +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"ïÇ̉ÁÎÉ̃ÅÎÉÑ:\n" +" -G, --traditional ĐÏÄÁ×̀ÑÔØ ×ÓÅ GNU ̉ÁÓÛÉ̉ÅÎÉÑ\n" +" -H, --hashsize=PRIME ƠÓÔÁÎÏ×ÉÔØ ̉ÁÚÍÅ̉ ÈÜÛ-ÔÁẦÉĂÙ Ä̀Ñ ĐÏÉÓËÁ " +"ÓÉÍ×Ï̀Ï×\n" +" -L, --nesting-limit=NUMBER ÉÚÍÅÎÉÔØ Đ̉ÅÄÅ̀ Ç̀ƠÂÉÎÙ ÉÎÔÅ̀ÅËÔƠÁ̀ØÎÏÇÏ " +"ĐÏÉÓËÁ\n" + +#: src/m4.c:170 +msgid "" +"\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" +msgstr "" +"\n" +"ầÏËÉ̉Ï×ÁÎÎÙÅ ÆÁỀÙ:\n" +" -F, --freeze-state=FILE × ËÏÎĂÅ ÓÏÚÄÁÔØ ÏẨÁÚ ĐÁÍÑÔÉ Ä̀Ñ FILE\n" +" -R, --reload-state=FILE × ÎÁ̃Á̀Å ÚÁÇ̉ƠÖÁÔØ ÏẨÁÚ ĐÁÍÑÔÉ Ä̀Ñ FILE\n" + +#: src/m4.c:176 +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"ïỒÁÄËÁ:\n" +" -d, --debug=[FLAGS] ƠÓÔÁÎÏ×ÉÔØ ỞÏ×ÅÎØ ÏỒÁÄËÉ (ĐÏ ƠÍÏ̀̃ÁÎÉÀ " +"FLAGS=`aeq')\n" +" -t, --trace=NAME ỔÁÓÓÉ̉Ï×ÁÔØ NAME ËÏÇÄÁ ÏÎÏ ÂƠÄÅÔ ÏĐ̉ÅÄÅ̀ÅÎÏ\n" +" -l, --arglength=NUM ƠÓÔÁÎÏ×ÉÔØ ̉ÁÚÍÅ̉ ỔÁÓÓÉ̉Ï×ËÉ Ä̀Ñ ÍÁË̉ÏÓÁ\n" +" -o, --error-output=FILE ĐÅ̉ÅÎÁĐ̉Á×ÉÔØ ÏỒÁÄÏ̃ÎÙÊ É ỔÁÓÓÉ̉Ï×Ï̃ÎÙÊ " +"×Ù×ÏÄ × ÆÁỀ FILE\n" + +#: src/m4.c:184 +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"FLAGS is any of:\n" +" t ỔÁÓÓÉ̉Ï×ÁÔØ ×ÓÅ ×ÙÚÏ×Ù ÍÁË̉ÏÓÏ×\n" +" a ĐÏËÁÚÁÔØ ÔÅËƠƯÉÅ Á̉ÇƠÍÅÎÔÙ\n" +" e ĐÏËÁÚÙ×ÁÔØ ÍÁË̉Ï̉ÁÓÛÉ̉ÅÎÉÅ\n" +" q ÚÁË̀À̃ÁÔØ ÚÎÁ̃ÅÎÉÑ × ËÁ×Ù̃ËÉ ĐÏ ÎÅÏÂÈÏÄÉÍÏÓÔÉ, Ó a É̀É e Æ̀ÁÇÁÍÉ\n" +" c ĐÏËÁÚÙ×ÁÔØ ĐÅ̉ÅÄ ÓÂÏ̉ÏÍ , ĐÏÓ̀Å ÓÂÏ̉Á É ĐÏÓ̀Å ×ÙÚÏ×Á\n" +" x ÄÏÂÁ×̀ÑÔØ ƠÎÉËÁ̀ØÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏ̉ ×ÙÚÏ×Á ÍÁË̉ÏÓÁ, ÉÓĐÏ̀ØÚƠÅÔÓÑ ×ÍÅÓÔÅ " +"Ó Æ̀ÁÇÏÍ c\n" +" f ×Ù×ÏÄÉÔØ ÔÅËƠƯÅÅ ÉÍÑ ×ÈÏÄÎÏÇÏ ÆÁỀÁ\n" +" l ×Ù×ÏÄÉÔØ ÎÏÍÅ̉ ÔÅËƠƯÅÊ ÓỔÏ̃ËÉ\n" +" p ĐÏËÁÚÙ×ÁÔØ ̉ÅÚỜØÔÁÔÙ ĐÏÉÓËÁ ĐÏ ĐƠÔÑÍ\n" +" i ĐÏËÁÚÙ×ÁÔØ ÉÚÍÅÎÅÎÉÑ ×Ï ×ÈÏÄÎÙÈ ÆÁỀÁÈ\n" +" V ÓÏË̉ÁƯÅÎÉÅ Ä̀Ñ ×ÓÅÈ Æ̀ÁÇÏ× ×ÍÅÓÔÅ\n" + +#: src/m4.c:199 +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"åÓ̀É FILE ÎÅ ÓƠƯÅÓÔ×ƠÅÔ É̀É FILE ÜÔÏ `-', ÉÓĐÏ̀ØÚƠÅÔÓÑ ÓÔÁÎÄÁ̉ÔÎÙÊ ×ÈÏÄ.\n" + +#: src/m4.c:358 +#, c-format +msgid "Bad debug flags: `%s'" +msgstr "îÅ×Å̉ÎÙÊ Æ̀ÁÇ ÏỒÁÄËÉ: '%s'" + +#: src/m4.c:437 +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ËÏÄ × ËÏÓ×ÅÎÎÙÈ Á̉ÇƠÍÅÎÔÁÈ" + +#: src/macro.c:92 +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ̀ÅËÓÅÍÙ × expand_token ()" + +#: src/macro.c:158 +msgid "ERROR: EOF in argument list" +msgstr "ïûéâëá: ëÏÎÅĂ ÆÁỀÁ × ÓĐÉÓËÅ Á̉ÇƠÍÅÎÔÏ×" + +#: src/macro.c:176 +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ̀ÅËÓÅÍÙ × expand_argument ()" + +#: src/macro.c:253 +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "÷îơộåîîññ ïûéâëá: îÅ×Å̉ÎÙÊ ÔÉĐ ÓÉÍ×Ï̀Á × call_macro ()" + +#: src/macro.c:282 +#, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "" +"ïûéâëá: ́ÉÍÉÔ ̉ÅËỞÓÉÉ %d ÉÓ̃Å̉ĐÁÎ, ÉÓĐÏ̀ØÚƠÊÔÅ -L<N> ̃ÔÏÂÙ ÉÚÍÅÎÉÔØ ÅÇÏ" + +#: src/output.c:198 +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "ïûéâëá: îÅ ÍÏÇƠ ÓÏÚÄÁÔØ ×̉ÅÍÅÎÎÙÊ ÆÁỀ Ä̀Ñ ̉ÁÚ×ÅÔ×̀ÅÎÉÑ ÍÁË̉ÏÏẨÁÂÏÔËÉ" + +#: src/output.c:208 +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "ïûéâëá: îÅ ÍÏÇƠ ÚÁĐÉÓÁÔØ ̉ÁÚ×ÅÔ×̀ÅÎÉÅ ×Ï ×̉ÅÍÅÎÎÙÊ ÆÁỀ" + +#: src/output.c:292 +msgid "ERROR: Copying inserted file" +msgstr "ïûéâëá: ëÏĐÉ̉ƠÀ ×ÓÔÁ×̀ÅÎÎÙÊ ÆÁỀ" + +#: src/output.c:473 +msgid "ERROR: Reading inserted file" +msgstr "ïûéâëá: ₫ÉÔÁÀ ×ÓÔÁ×̀ÅÎÎÙÊ ÆÁỀ" + +#: src/output.c:572 +msgid "Cannot stat diversion" +msgstr "îÅ×ÏÚÍÏÖÎÏ ĐÏÄÓ̃ÉÔÁÔØ ̉ÁÚ×ÅÔ×̀ÅÎÉÅ" + +#: src/path.c:131 +#, c-format +msgid "Path search for `%s' found `%s'" +msgstr "đƠÔØ ĐÏÉÓËÁ Ä̀Ñ `%s' ÎÁÊÄÅÎ `%s'" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +msgid "VMEM limit exceeded?\n" +msgstr "ëÏÎ̃É̀ÁÓØ ×É̉ÔƠÁ̀ØÎÁÑ ĐÁÍÑÔØ?\n" + +#: src/stackovf.c:190 +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"ïÂÎÁ̉ƠÖÅÎ ×ÙÈÏÄ ÚÁ Ç̉ÁÎÉĂƠ ĐÁÍÑÔÉ (SIGSEGV). üÔÏ ̀ÉÂÏ ĐÅ̉ÅĐÏ̀ÎÅÎÉÅ ÓÔÅËÁ\n" +"É̀É ÏÛÉÂËÁ × " + +#: src/stackovf.c:195 +msgid ". Check for possible infinite recursion.\n" +msgstr ". đ̉Ï×Å̉ËÁ ÎÁ ×ÏÚÍÏÖÎƠÀ ÂÅÓËÏÎÅ̃ÎƠÀ ̉ÅËỞÓÉÀ.\n" + +#: src/symtab.c:190 +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "÷îơộåîîññ ïûéâëá: ÎÅ×Å̉ÎÙÊ ̉ÅÖÉÍ Ä̀Ñ symbol_lookup ()" + +#: src/symtab.c:243 +#, c-format +msgid "Name `%s' is unknown\n" +msgstr "éÍÑ `%s' ÎÅÉÚ×ÅÓÔÎÏ\n" + +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "îÅ×Å̉ÎÏÅ ̉ÅÇỜÑ̉ÎÏÅ ×Ù̉ÁÖÅÎÉÅ: '%s': %s" + +#~ msgid "%s: option `%s' is ambiguous\n" +#~ msgstr "%s: ÏĐĂÉÑ `%s' ÎÅÏÄÎÏÚÎÁ̃ÎÁ\n" + +#~ msgid "%s: option `--%s' doesn't allow an argument\n" +#~ msgstr "%s: Ơ ÏĐĂÉÉ `--%s' ÎÅ ÄÏ̀ÖÎÏ ÂÙÔØ Á̉ÇƠÍÅÎÔÏ×\n" + +#~ msgid "%s: option `%c%s' doesn't allow an argument\n" +#~ msgstr "%s: Ơ ÏĐĂÉÉ `%c%s' ÎÅ ÄÏ̀ÖÎÏ ÂÙÔØ Á̉ÇƠÍÅÎÔÏ×\n" + +#~ msgid "%s: option `%s' requires an argument\n" +#~ msgstr "%s: Ơ ÏĐĂÉÉ `%s' ÄÏ̀ÖÅÎ ÂÙÔØ Á̉ÇƠÍÅÎÔ\n" + +#~ msgid "%s: unrecognized option `--%s'\n" +#~ msgstr "%s: ÎÅÉÚ×ÅÓÔÎÁÑ ÏĐĂÉÑ `--%s'\n" + +#~ msgid "%s: unrecognized option `%c%s'\n" +#~ msgstr "%s: ÎÅÉÚ×ÅÓÔÎÁÑ ÏĐĂÉÑ '%c%s'\n" + +#~ msgid "%s: illegal option -- %c\n" +#~ msgstr "%s: ÚÁĐ̉ÅƯÅÎÎÁÑ ÏĐĂÉÑ -- %c\n" + +#~ msgid "%s: invalid option -- %c\n" +#~ msgstr "%s: ÎÅ×Å̉ÎÁÑ ÏĐĂÉÑ -- %c\n" + +#~ msgid "%s: option requires an argument -- %c\n" +#~ msgstr "%s: ÏĐĂÉÉ ÎÅÏÂÈÏÄÉÍ Á̉ÇƠÍÅÎÔ -- %c\n" + +#~ msgid "No previous regular expression" +#~ msgstr "îÅÔ Đ̉ÅÄÛÅÄÓÔ×ƠÀƯÅÇÏ ̉ÅÇỜÑ̉ÎÏÇÏ ×Ù̉ÁÖÅÎÉÑ" + +#~ msgid "Memory exhausted" +#~ msgstr "đÁÍÑÔØ ÉÓ̃Å̉ĐÁÎÁ" diff --git a/po/stamp-cat-id b/po/stamp-cat-id new file mode 100644 index 00000000..9788f702 --- /dev/null +++ b/po/stamp-cat-id @@ -0,0 +1 @@ +timestamp diff --git a/po/sv.gmo b/po/sv.gmo Binary files differnew file mode 100644 index 00000000..2cebf070 --- /dev/null +++ b/po/sv.gmo diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 00000000..73ef692a --- /dev/null +++ b/po/sv.po @@ -0,0 +1,549 @@ +# Swedish messages for m4 +# Copyright (C) 1996 Free Software Foundation, Inc. +# <Jan.Djarv@mbox200.swipnet.se>, 1996. +# $Revision$ +# +msgid "" +msgstr "" +"Project-Id-Version: m4 1.4.3\n" +"POT-Creation-Date: 1998-08-03 17:14+0200\n" +"PO-Revision-Date: $Date$\n" +"Last-Translator: Jan Djärv <Jan.Djarv@mbox200.swipnet.se>\n" +"Language-Team: Swedish <sv@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: src/builtin.c:272 +#, fuzzy, c-format +msgid "Warning: Too few arguments to built-in `%s'" +msgstr "Varning: För få argument till inbyggt makro \"%s\"" + +#: src/builtin.c:278 +#, fuzzy, c-format +msgid "Warning: Excess arguments to built-in `%s' ignored" +msgstr "Varning: Överskottsargument till inbyggt makro \"%s\" ignorerade" + +#: src/builtin.c:298 +#, fuzzy, c-format +msgid "Non-numeric argument to built-in `%s'" +msgstr "Ickenumeriskt argument till inbyggt makro \"%s\"" + +#: src/builtin.c:438 +#, fuzzy +msgid "INTERNAL ERROR: Bad token data type in define_macro ()" +msgstr "INTERNT FEL: Otillåten lexikalisk datatyp i define_macro ()" + +#: src/builtin.c:608 src/builtin.c:671 src/builtin.c:1188 src/builtin.c:1212 +#, fuzzy, c-format +msgid "Undefined name %s" +msgstr "Odefinierat namn \"%s\"" + +#: src/builtin.c:636 +#, fuzzy +msgid "INTERNAL ERROR: Builtin not found in builtin table!" +msgstr "INTERNT FEL: Inbyggt makro finns inte i tabellen!" + +#: src/builtin.c:644 +#, fuzzy +msgid "INTERNAL ERROR: Bad token data type in m4_dumpdef ()" +msgstr "INTERNT FEL: Otillåten lexikalisk datatyp i m4_dumpdef ()" + +#: src/builtin.c:695 +#, fuzzy, c-format +msgid "Undefined macro `%s'" +msgstr "Odefinierat makro \"%s\"" + +#: src/builtin.c:735 +#, fuzzy +msgid "INTERNAL ERROR: Bad symbol type in m4_defn ()" +msgstr "INTERNT FEL: Otillåten symboltyp i m4_defn ()" + +#: src/builtin.c:772 +#, fuzzy, c-format +msgid "Cannot open pipe to command `%s'" +msgstr "Kan inte skapa rör till kommandot \"%s\"" + +#: src/builtin.c:811 +#, fuzzy, c-format +msgid "Radix in eval out of range (radix = %d)" +msgstr "Otillåten bas i \"eval\" (bas = %d)" + +#: src/builtin.c:820 +#, fuzzy +msgid "Negative width to eval" +msgstr "Negativ bredd till \"eval\"" + +#: src/builtin.c:925 +#, fuzzy, c-format +msgid "Non-numeric argument to %s" +msgstr "Ickenumeriskt argument till %s" + +#: src/builtin.c:937 +#, fuzzy, c-format +msgid "Cannot undivert %s" +msgstr "Kan inte återleda %s" + +#: src/builtin.c:1043 src/freeze.c:207 +#, fuzzy, c-format +msgid "Cannot open %s" +msgstr "Kan inte öppna %s" + +#: src/builtin.c:1248 +#, fuzzy, c-format +msgid "Debugmode: bad debug flags: `%s'" +msgstr "Felsökningsläge: okänd flagga: \"%s\"" + +#: src/builtin.c:1284 +#, fuzzy, c-format +msgid "Cannot set error file: %s" +msgstr "Kan inte sätta felutskriftsfil: %s" + +#: src/builtin.c:1501 +#, fuzzy +msgid "WARNING: \\0 will disappear, use \\& instead in replacements" +msgstr "VARNING: \\0 kommer att försvinna, använd \\& i ersättningar" + +#: src/builtin.c:1562 src/builtin.c:1622 src/input.c:637 +#, fuzzy, c-format +msgid "Bad regular expression `%s': %s" +msgstr "Otillåtet reguljäruttryck \"%s\": %s" + +#: src/builtin.c:1573 src/builtin.c:1646 +#, fuzzy, c-format +msgid "Error matching regular expression `%s'" +msgstr "Reguljäruttrycket \"%s\" matchar inte" + +#: src/debug.c:379 +#, fuzzy +msgid "INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())" +msgstr "INTERNT FEL: Inbyggt makro finns inte i tabellen (trace_pre ())" + +#: src/debug.c:387 +#, fuzzy +msgid "INTERNAL ERROR: Bad token data type (trace_pre ())" +msgstr "INTERNT FEL: Otillåten lexikalisk datatyp (trace_pre ())" + +#: src/eval.c:277 +#, fuzzy, c-format +msgid "Bad expression in eval (missing right parenthesis): %s" +msgstr "Otillåtet uttryck i \"eval\" (högerparentes saknas): %s" + +#: src/eval.c:283 +#, fuzzy, c-format +msgid "Bad expression in eval: %s" +msgstr "Otillåtet uttryck i \"eval\": %s" + +#: src/eval.c:288 +#, fuzzy, c-format +msgid "Bad expression in eval (bad input): %s" +msgstr "Otillåtet uttryck i \"eval\" (otillåtet indata): %s" + +#: src/eval.c:293 +#, fuzzy, c-format +msgid "Bad expression in eval (excess input): %s" +msgstr "Otillåtet uttryck i \"eval\" (för mycket indata): %s" + +#: src/eval.c:298 +#, fuzzy, c-format +msgid "Divide by zero in eval: %s" +msgstr "Division med noll i \"eval\": %s" + +#: src/eval.c:303 +#, fuzzy, c-format +msgid "Modulo by zero in eval: %s" +msgstr "Modulo med noll i \"eval\": %s" + +#: src/eval.c:308 +#, fuzzy +msgid "INTERNAL ERROR: Bad error code in evaluate ()" +msgstr "INTERNT FEL: Otillåten felkod i evaluate ()" + +#: src/eval.c:547 +#, fuzzy +msgid "INTERNAL ERROR: Bad comparison operator in cmp_term ()" +msgstr "INTERNT FEL: Otillåten jämförelseoperator i cmp_term ()" + +#: src/eval.c:590 +#, fuzzy +msgid "INTERNAL ERROR: Bad shift operator in shift_term ()" +msgstr "INTERNT FEL: Otillåten skiftoperator i shift_term ()" + +#: src/eval.c:674 +#, fuzzy +msgid "INTERNAL ERROR: Bad operator in mult_term ()" +msgstr "INTERNT FEL: Otillåten operator i mult_term ()" + +#: src/freeze.c:115 +#, fuzzy +msgid "INTERNAL ERROR: Built-in not found in builtin table!" +msgstr "INTERNT FEL: Inbyggt makro finns inte i tabellen!" + +#: src/freeze.c:128 +#, fuzzy +msgid "INTERNAL ERROR: Bad token data type in freeze_one_symbol ()" +msgstr "INTERNT FEL: Otillåten lexikalisk datatyp i freeze_one_symbol ()" + +#: src/freeze.c:159 +#, fuzzy +msgid "Expecting line feed in frozen file" +msgstr "Förväntar nyrad i fryst fil" + +#: src/freeze.c:161 +#, fuzzy, c-format +msgid "Expecting character `%c' in frozen file" +msgstr "Förväntar tecknet \"%c\" i fryst fil" + +#: src/freeze.c:218 +#, fuzzy +msgid "Ill-formated frozen file" +msgstr "Korrupt fryst fil" + +#: src/freeze.c:273 src/freeze.c:289 +#, fuzzy +msgid "Premature end of frozen file" +msgstr "För tidigt filslut i fryst fil" + +#: src/freeze.c:323 +#, fuzzy, c-format +msgid "`%s' from frozen file not found in builtin table!" +msgstr "\"%s\" från fryst fil hittades inte i tabellen för inbyggda makron!" + +#: src/input.c:174 +#, fuzzy, c-format +msgid "Input read from %s" +msgstr "Indata läses från %s" + +#: src/input.c:231 +#, fuzzy +msgid "INTERNAL ERROR: Recursive push_string!" +msgstr "INTERNT FEL: Rekursiv push_string!" + +#: src/input.c:311 +#, fuzzy, c-format +msgid "Input reverted to %s, line %d" +msgstr "Indata återgår till %s, rad %d" + +#: src/input.c:325 +#, fuzzy +msgid "INTERNAL ERROR: Input stack botch in pop_input ()" +msgstr "INTERNT FEL: Instacken havererade i pop_input ()" + +#: src/input.c:364 +#, fuzzy +msgid "INTERNAL ERROR: Bad call to init_macro_token ()" +msgstr "INTERNT FEL: Otillåtet anrop till init_macro_token ()" + +#: src/input.c:413 +#, fuzzy +msgid "INTERNAL ERROR: Input stack botch in peek_input ()" +msgstr "INTERNT FEL: Instacken havererade i peek_input ()" + +#: src/input.c:470 +#, fuzzy +msgid "INTERNAL ERROR: Input stack botch in next_char ()" +msgstr "INTERNT FEL: Instacken havererade i next_char ()" + +#: src/input.c:550 +#, fuzzy +msgid "NONE" +msgstr "INGET" + +#: src/input.c:777 +#, fuzzy +msgid "ERROR: EOF in string" +msgstr "FEL: Filslut i sträng" + +#: src/m4.c:106 +#, fuzzy +msgid "ERROR: Stack overflow. (Infinite define recursion?)" +msgstr "FEL: Stacken flödar över. (Oändlig rekursion?)" + +#: src/m4.c:133 +#, fuzzy, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "Försök med \"%s --help\" för mer information.\n" + +#: src/m4.c:137 +#, fuzzy, c-format +msgid "Usage: %s [OPTION]... [FILE]...\n" +msgstr "Användning: %s [FLAGGA]... [FIL]...\n" + +#: src/m4.c:138 +#, fuzzy +msgid "" +"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, --interactive unbuffer output, ignore interrupts\n" +" -E, --fatal-warnings stop execution after first warning\n" +" -Q, --quiet, --silent suppress some warnings for builtins\n" +" -P, --prefix-builtins force a `m4_' prefix to all builtins\n" +msgstr "" +"Obligatoriska respektive valfria argument för långa flaggor är\n" +"obligatoriska respektive valfria även för korta flaggor.\n" +"\n" +"Körlägen:\n" +" --help visa denna hjälptext och avsluta\n" +" --version visa versionsinformation och avsluta\n" +" -e, --interactive obuffrad utskrift, ignorera avbrott\n" +" -E, --fatal-warnings avsluta exekvering efter första varningen\n" +" -Q, --quiet, --silent undertryck vissa varningar för inbyggda " +"makron\n" +" -P, --prefix-builtins alla inbyggda makron börjar med `m4_'\n" + +#: src/m4.c:151 +#, fuzzy +msgid " -W, --word-regexp=REGEXP use REGEXP for macro name syntax\n" +msgstr " -W, --word-regexp=REGEXP använd REGEXP som makronamnsyntax\n" + +#: src/m4.c:155 +#, fuzzy +msgid "" +"\n" +"Preprocessor features:\n" +" -I, --include=DIRECTORY search this directory second for includes\n" +" -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n" +" -U, --undefine=NAME delete builtin NAME\n" +" -s, --synclines generate `#line NO \"FILE\"' lines\n" +msgstr "" +"\n" +"Förprocessorstyrning:\n" +" -I, --include=KATALOG sök i katalog efter inkluderade filer\n" +" -D, --define=NAMN[=VÄRDE] definiera NAMN som VÄRDE, eller tomt\n" +" -U, --undefine=NAMN ta bort inbyggt makro\n" +" -s, --synclines generera `#line NNN \"FIL\"' rader\n" + +#: src/m4.c:163 +#, fuzzy +msgid "" +"\n" +"Limits control:\n" +" -G, --traditional suppress all GNU extensions\n" +" -H, --hashsize=PRIME set symbol lookup hash table size\n" +" -L, --nesting-limit=NUMBER change artificial nesting limit\n" +msgstr "" +"\n" +"Begränsningskontroll:\n" +" -G, --traditional undertryck alla extra GNU tillägg\n" +" -H, --hashsize=PRIMTAL sätt storlek på symboltabellen\n" +" -L, --nesting-limit=NUMMER ändra artificiell nästningsnivå\n" + +#: src/m4.c:170 +#, fuzzy +msgid "" +"\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" +msgstr "" +"\n" +"Frysta tillståndsfiler:\n" +" -F, --freeze-state=FIL spara fryst tillstånd i FIL i slutet\n" +" -R, --reload-state=FIL läs fryst tillstånd från FIL i början\n" + +#: src/m4.c:176 +#, fuzzy +msgid "" +"\n" +"Debugging:\n" +" -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n" +" -t, --trace=NAME trace NAME when it will be defined\n" +" -l, --arglength=NUM restrict macro tracing size\n" +" -o, --error-output=FILE redirect debug and trace output\n" +msgstr "" +"\n" +"Felsökning:\n" +" -d, --debug=[FLAGGOR] sätt felsökningsnivå\n" +" (inga FLAGGOR tolkas som \"aeq\")\n" +" -t, --trace=NAMN spåra NAMN när den blir definierad\n" +" -l, --arglength=NUMMER begränsa makrospårningsstorleken\n" +" -o, --error-output=FIL avled felsöknings och spårutskrifter till " +"FIL\n" + +#: src/m4.c:184 +#, fuzzy +msgid "" +"\n" +"FLAGS is any of:\n" +" t trace for all macro calls, not only traceon'ed\n" +" a show actual arguments\n" +" e show expansion\n" +" q quote values as necessary, with a or e flag\n" +" c show before collect, after collect and after call\n" +" x add a unique macro call id, useful with c flag\n" +" f say current input file name\n" +" l say current input line number\n" +" p show results of path searches\n" +" i show changes in input files\n" +" V shorthand for all of the above flags\n" +msgstr "" +"\n" +"FLAGGOR kan vara en eller flera av:\n" +" t spåra alla makroanrop, inte bara de som spåras med \"traceon\"\n" +" a visa aktuella argument\n" +" e visa expansioner\n" +" q sätt citationstecken där det behövs, gäller \"a\" och \"e\"\n" +" c visa före insamling, efter insamling och efter anrop\n" +" x lägg till en unik identifierare för makroanrop, användbart med \"c\"\n" +" f visa namnet på aktuell infil\n" +" l visa raden i aktuell infil\n" +" p visa resultatet av sökvägssökningar\n" +" i visa byten av infil\n" +" V förkortning för alla ovanstående flaggor\n" + +#: src/m4.c:199 +#, fuzzy +msgid "" +"\n" +"If no FILE or if FILE is `-', standard input is read.\n" +msgstr "" +"\n" +"Om ingen FIL anges eller om FIL är `-', så läses standard in.\n" + +#: src/m4.c:358 +#, fuzzy, c-format +msgid "Bad debug flags: `%s'" +msgstr "Okänd felsökningsflagga \"%s\"" + +#: src/m4.c:437 +#, fuzzy +msgid "INTERNAL ERROR: Bad code in deferred arguments" +msgstr "INTERNT FEL: Otillåten kod i argument" + +#: src/macro.c:92 +#, fuzzy +msgid "INTERNAL ERROR: Bad token type in expand_token ()" +msgstr "INTERNT FEL: Otillåten lexikalisk datatyp i expand_token ()" + +#: src/macro.c:158 +#, fuzzy +msgid "ERROR: EOF in argument list" +msgstr "FEL: Filslut i argumentlistan" + +#: src/macro.c:176 +#, fuzzy +msgid "INTERNAL ERROR: Bad token type in expand_argument ()" +msgstr "INTERNT FEL: Otillåten lexikalisk datatyp i expand_argument ()" + +#: src/macro.c:253 +#, fuzzy +msgid "INTERNAL ERROR: Bad symbol type in call_macro ()" +msgstr "INTERNT FEL: Otillåten symboltyp i call_macro ()" + +#: src/macro.c:282 +#, fuzzy, c-format +msgid "ERROR: Recursion limit of %d exceeded, use -L<N> to change it" +msgstr "FEL: Rekursionsgräns %d överskriden, använd -L<N> för att ändra" + +#: src/output.c:198 +#, fuzzy +msgid "ERROR: Cannot create temporary file for diversion" +msgstr "FEL: Kan inte skapa temporär fil för avledning" + +#: src/output.c:208 +#, fuzzy +msgid "ERROR: Cannot flush diversion to temporary file" +msgstr "FEL: Kan inte skriva avledningen till temporär fil" + +#: src/output.c:292 +#, fuzzy +msgid "ERROR: Copying inserted file" +msgstr "FEL: Kopiering av insatt fil" + +#: src/output.c:473 +#, fuzzy +msgid "ERROR: Reading inserted file" +msgstr "FEL: Läsning av insatt fil" + +#: src/output.c:572 +#, fuzzy +msgid "Cannot stat diversion" +msgstr "Kan inte ta status på avledningen" + +#: src/path.c:131 +#, fuzzy, c-format +msgid "Path search for `%s' found `%s'" +msgstr "\"%s\" hittades som \"%s\" i sökvägen" + +#. sbrk failed. Assume the RLIMIT_VMEM prevents expansion even +#. if the stack limit has not been reached. +#: src/stackovf.c:168 +#, fuzzy +msgid "VMEM limit exceeded?\n" +msgstr "VMEM begränsning överskriden?\n" + +#: src/stackovf.c:190 +#, fuzzy +msgid "" +"Memory bounds violation detected (SIGSEGV). Either a stack overflow\n" +"occurred, or there is a bug in " +msgstr "" +"Otillåten referens utanför minnesgränserna har upptäckts (SIGSEGV).\n" +"Antingen flödade stacken över eller så är det ett fel i " + +#: src/stackovf.c:195 +#, fuzzy +msgid ". Check for possible infinite recursion.\n" +msgstr ". Kontrollera om oändlig rekursion förekommer.\n" + +#: src/symtab.c:190 +#, fuzzy +msgid "INTERNAL ERROR: Illegal mode to symbol_lookup ()" +msgstr "INTERNT FEL: Otillåtet läge till symbol_lookup ()" + +#: src/symtab.c:243 +#, fuzzy, c-format +msgid "Name `%s' is unknown\n" +msgstr "Namnet \"%s\" är okänt\n" + +#, fuzzy +#~ msgid "Bad regular expression: `%s': %s" +#~ msgstr "Otillåtet reguljäruttryck \"%s\": %s" + +#, fuzzy +#~ msgid "%s: option `%s' is ambiguous\n" +#~ msgstr "%s: flaggan \"%s\" är tvetydig\n" + +#, fuzzy +#~ msgid "%s: option `--%s' doesn't allow an argument\n" +#~ msgstr "%s: flaggan \"--%s\" tar inget argument\n" + +#, fuzzy +#~ msgid "%s: option `%c%s' doesn't allow an argument\n" +#~ msgstr "%s: flaggan \"%c%s\" tar inget argument\n" + +#, fuzzy +#~ msgid "%s: option `%s' requires an argument\n" +#~ msgstr "%s: flaggan \"%s\" behöver ett argument\n" + +#, fuzzy +#~ msgid "%s: unrecognized option `--%s'\n" +#~ msgstr "%s: okänd flagga \"--%s\"\n" + +#, fuzzy +#~ msgid "%s: unrecognized option `%c%s'\n" +#~ msgstr "%s: okänd flagga \"%c%s\"\n" + +#, fuzzy +#~ msgid "%s: illegal option -- %c\n" +#~ msgstr "%s: otillåten flagga -- %c\n" + +#, fuzzy +#~ msgid "%s: invalid option -- %c\n" +#~ msgstr "%s: ogiltig flagga -- %c\n" + +#, fuzzy +#~ msgid "%s: option requires an argument -- %c\n" +#~ msgstr "%s: flaggan behöver ett argument -- %c\n" + +#, fuzzy +#~ msgid "No previous regular expression" +#~ msgstr "Inget föregående reguljäruttryck" + +#, fuzzy +#~ msgid "Memory exhausted" +#~ msgstr "Minnet slut" diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..00e8b063 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,15 @@ +AUTOMAKE_OPTIONS = ansi2knr +CATALOGS = fr.msg +LIBS = @LIBS@ +STACKOVF = @STACKOVF@ + +bin_PROGRAMS = m4 + +INCLUDES = -I$(top_srcdir) -I$(srcdir) -I$(top_srcdir)/lib + +m4_SOURCES = m4.c m4.h builtin.c debug.c eval.c format.c freeze.c input.c \ + macro.c output.c path.c symtab.c stackovf.c + +m4_LDADD = ../lib/libm4.a @INTLLIBS@ + + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000..eb20b843 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,122 @@ +# Makefile for GNU m4 sources. +# Copyright (C) 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +PRODUCT = @PRODUCT@ +VERSION = @VERSION@ + +SHELL = /bin/sh +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +STACKOVF = @STACKOVF@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +transform = @program_transform_name@ +bindir = $(exec_prefix)/bin + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LINK = $(CC) $(LDFLAGS) -o $@ + +.SUFFIXES: +.SUFFIXES: .c .o +.c.o: + $(COMPILE) $< + +ANSI2KNR = @ANSI2KNR@ +O = .@U@o + +.SUFFIXES: ._c ._o +.c._c: + ./ansi2knr --varargs $< > $@ +._c._o: + @echo $(COMPILE) $< + @rm -f _$*.c + @ln $< _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c +.c._o: + ./ansi2knr --varargs $< > $*._c + @echo $(COMPILE) $*._c + @rm -f _$*.c + @ln $*._c _$*.c && $(COMPILE) _$*.c && mv _$*.o $@ && rm _$*.c + +INCLUDES = -I.. -I$(srcdir) -I$(srcdir)/../lib + +HEADERS = m4.h +SOURCES = m4.c builtin.c debug.c eval.c format.c freeze.c input.c \ +macro.c output.c path.c stackovf.c symtab.c +OBJECTS = m4$O builtin$O debug$O eval$O format$O freeze$O input$O \ +macro$O output$O path$O $(STACKOVF) symtab$O + +DISTFILES = Makefile.in ansi2knr.c ansi2knr.1 $(HEADERS) $(SOURCES) \ +TAGS + +all: m4 + +m4: $(OBJECTS) ../lib/libm4.a + $(LINK) $(OBJECTS) ../lib/libm4.a $(LIBS) + +$(OBJECTS): $(ANSI2KNR) ../config.h m4.h ../lib/obstack.h +builtin$O: ../lib/regex.h + +ansi2knr: ansi2knr.o + $(LINK) ansi2knr.o $(LIBS) + +install: all + $(srcdir)/../mkinstalldirs $(bindir) + $(INSTALL_PROGRAM) m4 $(bindir)/`echo m4 | sed '$(transform)'` + +uninstall: + rm -f $(bindir)/`echo m4 | sed '$(transform)'` + +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) + cd $(srcdir) && etags -i ../lib/TAGS $(HEADERS) $(SOURCES) + +mostlyclean: + rm -f *.o *._c *._o core core.* + +clean: mostlyclean + rm -f m4 + +distclean: clean + rm -f Makefile ansi2knr + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + @echo "Copying distribution files" + @for file in $(DISTFILES); do \ + ln $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/src 2> /dev/null \ + || cp -p $(srcdir)/$$file ../$(PRODUCT)-$(VERSION)/src; \ + done + +Makefile: Makefile.in ../config.status + cd .. && CONFIG_FILES=src/$@ CONFIG_HEADERS= ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/ansi2knr.1 b/src/ansi2knr.1 new file mode 100644 index 00000000..434ce8f0 --- /dev/null +++ b/src/ansi2knr.1 @@ -0,0 +1,19 @@ +.TH ANSI2KNR 1 "31 December 1990" +.SH NAME +ansi2knr \- convert ANSI C to Kernighan & Ritchie C +.SH SYNOPSIS +.I ansi2knr +input_file output_file +.SH DESCRIPTION +If no output_file is supplied, output goes to stdout. +.br +There are no error messages. +.sp +.I ansi2knr +recognizes functions by seeing a non-keyword identifier at the left margin, followed by a left parenthesis, with a right parenthesis as the last character on the line. It will recognize a multi-line header if the last character on each line but the last is a left parenthesis or comma. These algorithms ignore whitespace and comments, except that the function name must be the first thing on the line. +.sp +The following constructs will confuse it: +.br + - Any other construct that starts at the left margin and follows the above syntax (such as a macro or function call). +.br + - Macros that tinker with the syntax of the function header. diff --git a/src/ansi2knr.c b/src/ansi2knr.c new file mode 100644 index 00000000..9bcc4adb --- /dev/null +++ b/src/ansi2knr.c @@ -0,0 +1,439 @@ +/* Copyright (C) 1989, 1991, 1993, 1994 Aladdin Enterprises. All rights reserved. */ + +/* ansi2knr.c */ +/* Convert ANSI function declarations to K&R syntax */ + +/* +ansi2knr is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY. No author or distributor accepts responsibility +to anyone for the consequences of using it or for whether it serves any +particular purpose or works at all, unless he says so in writing. Refer +to the GNU General Public License for full details. + +Everyone is granted permission to copy, modify and redistribute +ansi2knr, but only under the conditions described in the GNU +General Public License. A copy of this license is supposed to have been +given to you along with ansi2knr so you can know your rights and +responsibilities. It should be in a file named COPYLEFT. Among other +things, the copyright notice and this notice must be preserved on all +copies. +*/ + +/* + * Usage: + ansi2knr [--varargs] input_file [output_file] + * If no output_file is supplied, output goes to stdout. + * There are no error messages. + * + * ansi2knr recognizes function definitions by seeing a non-keyword + * identifier at the left margin, followed by a left parenthesis, + * with a right parenthesis as the last character on the line. + * It will recognize a multi-line header provided that the last character + * of the last line of the header is a right parenthesis, + * and no intervening line ends with a left brace or a semicolon. + * These algorithms ignore whitespace and comments, except that + * the function name must be the first thing on the line. + * The following constructs will confuse it: + * - Any other construct that starts at the left margin and + * follows the above syntax (such as a macro or function call). + * - Macros that tinker with the syntax of the function header. + * + * If the --varargs switch is supplied, ansi2knr will attempt to + * convert a ... argument to va_alist and va_dcl. If this switch is not + * supplied, ansi2knr will simply drop any such arguments. + */ + +/* + * The original and principal author of ansi2knr is L. Peter Deutsch + * <ghost@aladdin.com>. Other authors are noted in the change history + * that follows (in reverse chronological order): + lpd 94-10-10 removed CONFIG_BROKETS conditional + lpd 94-07-16 added some conditionals to help GNU `configure', + suggested by Francois Pinard <pinard@iro.umontreal.ca>; + properly erase prototype args in function parameters, + contributed by Jim Avera <jima@netcom.com>; + correct error in writeblanks (it shouldn't erase EOLs) + lpd 89-xx-xx original version + */ + +/* Most of the conditionals here are to make ansi2knr work with */ +/* the GNU configure machinery. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <ctype.h> + +#ifdef HAVE_CONFIG_H + +/* + For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). + This will define HAVE_CONFIG_H and so, activate the following lines. + */ + +# if STDC_HEADERS || HAVE_STRING_H +# include <string.h> +# else +# include <strings.h> +# endif + +#else /* not HAVE_CONFIG_H */ + +/* + Without AC_CONFIG_HEADER, merely use <string.h> as in the original + Ghostscript distribution. This loses on older BSD systems. + */ + +# include <string.h> + +#endif /* not HAVE_CONFIG_H */ + +#ifdef STDC_HEADERS +# include <stdlib.h> +#else +/* + malloc and free should be declared in stdlib.h, + but if you've got a K&R compiler, they probably aren't. + */ +char *malloc(); +void free(); +#endif + +/* Scanning macros */ +#define isidchar(ch) (isalnum(ch) || (ch) == '_') +#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_') + +/* Forward references */ +char *skipspace(); +void writeblanks(); +int test1(); +int convert1(); + +/* The main program */ +int +main(argc, argv) + int argc; + char *argv[]; +{ FILE *in, *out; +#define bufsize 5000 /* arbitrary size */ + char *buf; + char *line; + int convert_varargs = 0; + if ( argc > 1 && argv[1][0] == '-' ) + { if ( !strcmp(argv[1], "--varargs") ) + { convert_varargs = 1; + argc--; + argv++; + } + else + { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); + exit(1); + } + } + switch ( argc ) + { + default: + printf("Usage: ansi2knr [--varargs] input_file [output_file]\n"); + exit(0); + case 2: + out = stdout; + break; + case 3: + out = fopen(argv[2], "w"); + if ( out == NULL ) + { fprintf(stderr, "Cannot open output file %s\n", argv[2]); + exit(1); + } + } + in = fopen(argv[1], "r"); + if ( in == NULL ) + { fprintf(stderr, "Cannot open input file %s\n", argv[1]); + exit(1); + } + fprintf(out, "#line 1 \"%s\"\n", argv[1]); + buf = malloc(bufsize); + line = buf; + while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) + { switch ( test1(buf) ) + { + case 2: /* a function header */ + convert1(buf, out, 1, convert_varargs); + break; + case 1: /* a function */ + convert1(buf, out, 0, convert_varargs); + break; + case -1: /* maybe the start of a function */ + line = buf + strlen(buf); + if ( line != buf + (bufsize - 1) ) /* overflow check */ + continue; + /* falls through */ + default: /* not a function */ + fputs(buf, out); + break; + } + line = buf; + } + if ( line != buf ) fputs(buf, out); + free(buf); + fclose(out); + fclose(in); + return 0; +} + +/* Skip over space and comments, in either direction. */ +char * +skipspace(p, dir) + register char *p; + register int dir; /* 1 for forward, -1 for backward */ +{ for ( ; ; ) + { while ( isspace(*p) ) p += dir; + if ( !(*p == '/' && p[dir] == '*') ) break; + p += dir; p += dir; + while ( !(*p == '*' && p[dir] == '/') ) + { if ( *p == 0 ) return p; /* multi-line comment?? */ + p += dir; + } + p += dir; p += dir; + } + return p; +} + +/* + * Write blanks over part of a string. + * Don't overwrite end-of-line characters. + */ +void +writeblanks(start, end) + char *start; + char *end; +{ char *p; + for ( p = start; p < end; p++ ) + if ( *p != '\r' && *p != '\n' ) *p = ' '; +} + +/* + * Test whether the string in buf is a function definition. + * The string may contain and/or end with a newline. + * Return as follows: + * 0 - definitely not a function definition; + * 1 - definitely a function definition; + * 2 - definitely a function prototype (NOT USED); + * -1 - may be the beginning of a function definition, + * append another line and look again. + * The reason we don't attempt to convert function prototypes is that + * Ghostscript's declaration-generating macros look too much like + * prototypes, and confuse the algorithms. + */ +int +test1(buf) + char *buf; +{ register char *p = buf; + char *bend; + char *endfn; + int contin; + if ( !isidfirstchar(*p) ) + return 0; /* no name at left margin */ + bend = skipspace(buf + strlen(buf) - 1, -1); + switch ( *bend ) + { + case ';': contin = 0 /*2*/; break; + case ')': contin = 1; break; + case '{': return 0; /* not a function */ + default: contin = -1; + } + while ( isidchar(*p) ) p++; + endfn = p; + p = skipspace(p, 1); + if ( *p++ != '(' ) + return 0; /* not a function */ + p = skipspace(p, 1); + if ( *p == ')' ) + return 0; /* no parameters */ + /* Check that the apparent function name isn't a keyword. */ + /* We only need to check for keywords that could be followed */ + /* by a left parenthesis (which, unfortunately, is most of them). */ + { static char *words[] = + { "asm", "auto", "case", "char", "const", "double", + "extern", "float", "for", "if", "int", "long", + "register", "return", "short", "signed", "sizeof", + "static", "switch", "typedef", "unsigned", + "void", "volatile", "while", 0 + }; + char **key = words; + char *kp; + int len = endfn - buf; + while ( (kp = *key) != 0 ) + { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) + return 0; /* name is a keyword */ + key++; + } + } + return contin; +} + +/* Convert a recognized function definition or header to K&R syntax. */ +int +convert1(buf, out, header, convert_varargs) + char *buf; + FILE *out; + int header; /* Boolean */ + int convert_varargs; /* Boolean */ +{ char *endfn; + register char *p; + char **breaks; + unsigned num_breaks = 2; /* for testing */ + char **btop; + char **bp; + char **ap; + char *vararg = 0; + /* Pre-ANSI implementations don't agree on whether strchr */ + /* is called strchr or index, so we open-code it here. */ + for ( endfn = buf; *(endfn++) != '('; ) ; +top: p = endfn; + breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); + if ( breaks == 0 ) + { /* Couldn't allocate break table, give up */ + fprintf(stderr, "Unable to allocate break table!\n"); + fputs(buf, out); + return -1; + } + btop = breaks + num_breaks * 2 - 2; + bp = breaks; + /* Parse the argument list */ + do + { int level = 0; + char *lp = NULL; + char *rp; + char *end = NULL; + if ( bp >= btop ) + { /* Filled up break table. */ + /* Allocate a bigger one and start over. */ + free((char *)breaks); + num_breaks <<= 1; + goto top; + } + *bp++ = p; + /* Find the end of the argument */ + for ( ; end == NULL; p++ ) + { switch(*p) + { + case ',': + if ( !level ) end = p; + break; + case '(': + if ( !level ) lp = p; + level++; + break; + case ')': + if ( --level < 0 ) end = p; + else rp = p; + break; + case '/': + p = skipspace(p, 1) - 1; + break; + default: + ; + } + } + /* Erase any embedded prototype parameters. */ + if ( lp ) + writeblanks(lp + 1, rp); + p--; /* back up over terminator */ + /* Find the name being declared. */ + /* This is complicated because of procedure and */ + /* array modifiers. */ + for ( ; ; ) + { p = skipspace(p - 1, -1); + switch ( *p ) + { + case ']': /* skip array dimension(s) */ + case ')': /* skip procedure args OR name */ + { int level = 1; + while ( level ) + switch ( *--p ) + { + case ']': case ')': level++; break; + case '[': case '(': level--; break; + case '/': p = skipspace(p, -1) + 1; break; + default: ; + } + } + if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) + { /* We found the name being declared */ + while ( !isidfirstchar(*p) ) + p = skipspace(p, 1) + 1; + goto found; + } + break; + default: goto found; + } + } +found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) + { if ( convert_varargs ) + { *bp++ = "va_alist"; + vararg = p-2; + } + else + { p++; + if ( bp == breaks + 1 ) /* sole argument */ + writeblanks(breaks[0], p); + else + writeblanks(bp[-1] - 1, p); + bp--; + } + } + else + { while ( isidchar(*p) ) p--; + *bp++ = p+1; + } + p = end; + } + while ( *p++ == ',' ); + *bp = p; + /* Make a special check for 'void' arglist */ + if ( bp == breaks+2 ) + { p = skipspace(breaks[0], 1); + if ( !strncmp(p, "void", 4) ) + { p = skipspace(p+4, 1); + if ( p == breaks[2] - 1 ) + { bp = breaks; /* yup, pretend arglist is empty */ + writeblanks(breaks[0], p + 1); + } + } + } + /* Put out the function name and left parenthesis. */ + p = buf; + while ( p != endfn ) putc(*p, out), p++; + /* Put out the declaration. */ + if ( header ) + { fputs(");", out); + for ( p = breaks[0]; *p; p++ ) + if ( *p == '\r' || *p == '\n' ) + putc(*p, out); + } + else + { for ( ap = breaks+1; ap < bp; ap += 2 ) + { p = *ap; + while ( isidchar(*p) ) + putc(*p, out), p++; + if ( ap < bp - 1 ) + fputs(", ", out); + } + fputs(") ", out); + /* Put out the argument declarations */ + for ( ap = breaks+2; ap <= bp; ap += 2 ) + (*ap)[-1] = ';'; + if ( vararg != 0 ) + { *vararg = 0; + fputs(breaks[0], out); /* any prior args */ + fputs("va_dcl", out); /* the final arg */ + fputs(bp[0], out); + } + else + fputs(breaks[0], out); + } + free((char *)breaks); + return 0; +} diff --git a/src/builtin.c b/src/builtin.c new file mode 100644 index 00000000..47506018 --- /dev/null +++ b/src/builtin.c @@ -0,0 +1,1732 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Code for all builtin macros, initialisation of symbol table, and + expansion of user defined macros. */ + +#include "m4.h" + +extern FILE *popen (); + +#include "regex.h" + +#define ARG(i) (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "") + +/* Initialisation of builtin and predefined macros. The table + "builtin_tab" is both used for initialisation, and by the "builtin" + builtin. */ + +#define DECLARE(name) \ + static void name _((struct obstack *, int, token_data **)) + +DECLARE (m4___file__); +DECLARE (m4___line__); +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_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__ }, + { "builtin", TRUE, FALSE, TRUE, m4_builtin }, + { "changecom", FALSE, FALSE, FALSE, m4_changecom }, + { "changequote", FALSE, FALSE, FALSE, m4_changequote }, +#ifdef ENABLE_CHANGEWORD + { "changeword", TRUE, FALSE, FALSE, 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, FALSE, m4_errprint }, + { "esyscmd", TRUE, FALSE, TRUE, m4_esyscmd }, + { "eval", FALSE, FALSE, TRUE, m4_eval }, + { "format", TRUE, FALSE, FALSE, 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, FALSE, FALSE, m4_indir }, + { "len", FALSE, FALSE, TRUE, m4_len }, + { "m4exit", FALSE, FALSE, FALSE, m4_m4exit }, + { "m4wrap", FALSE, FALSE, FALSE, m4_m4wrap }, + { "maketemp", FALSE, FALSE, TRUE, m4_maketemp }, + { "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, FALSE, 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 }, +}; + +static predefined const +predefined_tab[] = +{ + { "unix", "__unix__", "" }, + { 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; + return NULL; +} + +/*-----------------------------------. +| Find the builtin, which has NAME. | +`-----------------------------------*/ + +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 NULL; +} + +/*-------------------------------------------------------------------------. +| 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, + boolean traced) +{ + 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; + SYMBOL_TRACED (sym) = traced; +} + +/*-------------------------------------------------------------------------. +| 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) + xfree (SYMBOL_TEXT (s)); + + SYMBOL_TYPE (s) = TOKEN_TEXT; + SYMBOL_TEXT (s) = xstrdup (text); +} + +/*-----------------------------------------------. +| Initialise 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, FALSE); + free (string); + } + else + define_builtin (bp->name, bp, SYMBOL_INSERT, FALSE); + + 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 boolean +bad_argc (token_data *name, int argc, int min, int max) +{ + boolean isbad = FALSE; + + if (min > 0 && argc < min) + { + if (!suppress_warnings) + M4ERROR ((warning_status, 0, + "Warning: Too few arguments to built-in `%s'", + TOKEN_DATA_TEXT (name))); + isbad = TRUE; + } + else if (max > 0 && argc > max && !suppress_warnings) + M4ERROR ((warning_status, 0, + "Warning: Excess arguments to built-in `%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 boolean +numeric_arg (token_data *macro, const char *arg, int *valuep) +{ + char *endp; + + if (*arg == 0 || (*valuep = strtol (arg, &endp, 10), *endp != 0)) + { + M4ERROR ((warning_status, 0, + "Non-numeric argument to built-in `%s'", + TOKEN_DATA_TEXT (macro))); + return FALSE; + } + 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 (register eval_t value, int radix) +{ + boolean negative; + unsigned_eval_t uvalue; + static char str[256]; + register 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, boolean 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) + 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, TOKEN_DATA_FUNC_TRACED (argv[2])); + break; + + default: + M4ERROR ((warning_status, 0, + "INTERNAL ERROR: Bad token data type in define_macro ()")); + abort (); + } + return; +} + +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) +{ + if (bad_argc (argv[0], argc, 2, 2)) + return; + lookup_symbol (ARG (1), 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) +{ + if (bad_argc (argv[0], argc, 2, 2)) + return; + lookup_symbol (ARG (1), 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) + 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, struct dump_symbol_data *data) +{ + 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 voidstar s1, const voidstar 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, (char *) &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 name %s", TOKEN_DATA_TEXT (argv[i]))); + } + } + + /* Make table of symbols invisible to expand_macro (). */ + + (void) obstack_finish (obs); + + qsort ((char *) 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 = ARG (1); + + if (bad_argc (argv[0], argc, 2, -1)) + return; + + bp = find_builtin_by_name (name); + if (bp == NULL) + M4ERROR ((warning_status, 0, + "Undefined name %s", name)); + else + (*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 = ARG (1); + + if (bad_argc (argv[0], argc, 1, -1)) + return; + + s = lookup_symbol (name, SYMBOL_LOOKUP); + if (s == NULL) + M4ERROR ((warning_status, 0, + "Undefined macro `%s'", name)); + else + 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 ht input stack. | +`-------------------------------------------------------------------------*/ + +static void +m4_defn (struct obstack *obs, int argc, token_data **argv) +{ + symbol *s; + + 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: + push_macro (SYMBOL_FUNC (s), SYMBOL_TRACED (s)); + 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. | +`------------------------------------------------------------------------*/ + +/* 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)) + return; + + debug_flush_files (); + sysval = system (ARG (1)); +} + +static void +m4_esyscmd (struct obstack *obs, int argc, token_data **argv) +{ + FILE *pin; + int ch; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + debug_flush_files (); + pin = popen (ARG (1), "r"); + if (pin == NULL) + { + M4ERROR ((warning_status, errno, + "Cannot open pipe to command \"%s\"", ARG (1))); + sysval = 0xff << 8; + } + 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 >> 8) & 0xff); +} + +/*-------------------------------------------------------------------------. +| 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; + int radix = 10; + int min = 1; + const char *s; + + if (bad_argc (argv[0], argc, 2, 4)) + return; + + if (argc >= 3 && !numeric_arg (argv[0], ARG (2), &radix)) + return; + + if (radix <= 1 || radix > (int) strlen (digits)) + { + M4ERROR ((warning_status, 0, + "Radix in eval out of range (radix = %d)", radix)); + return; + } + + if (argc >= 4 && !numeric_arg (argv[0], ARG (3), &min)) + return; + if (min <= 0) + { + M4ERROR ((warning_status, 0, + "Negative width to eval")); + return; + } + + if (evaluate (ARG (1), &value)) + return; + + s = ntoa (value, radix); + + if (*s == '-') + { + obstack_1grow (obs, '-'); + min--; + 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; + + if (argc == 1) + undivert_all (); + else + for (i = 1; i < argc; i++) + { + if (sscanf (ARG (i), "%d", &file) == 1) + insert_diversion (file); + else if (no_gnu_extensions) + M4ERROR ((warning_status, 0, + "Non-numeric argument to %s", TOKEN_DATA_TEXT (argv[0]))); + else + { + fp = path_search (ARG (i)); + if (fp != NULL) + { + insert_file (fp); + fclose (fp); + } + 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) +{ + 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; + + 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; + + if (argc == 1) + set_comment ("", ""); /* disable comments */ + else + set_comment (TOKEN_DATA_TEXT (argv[1]), + (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, boolean silent) +{ + FILE *fp; + + if (bad_argc (argv[0], argc, 2, 2)) + return; + + fp = path_search (ARG (1)); + if (fp == NULL) + { + if (!silent) + M4ERROR ((warning_status, errno, + "Cannot open %s", ARG (1))); + return; + } + + push_file (fp, ARG (1)); +} + +/*------------------------------------------------. +| 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__" and + "__line__". The last two are GNU specific. */ + +/*------------------------------------------------------------------. +| Use the first argument as at template for a temporary file name. | +`------------------------------------------------------------------*/ + +static void +m4_maketemp (struct obstack *obs, int argc, token_data **argv) +{ + if (bad_argc (argv[0], argc, 2, 2)) + return; + mktemp (ARG (1)); + obstack_grow (obs, ARG (1), strlen (ARG (1))); +} + +/*----------------------------------------. +| Print all arguments on standard error. | +`----------------------------------------*/ + +static void +m4_errprint (struct obstack *obs, int argc, token_data **argv) +{ + dump_args (obs, argc, argv, " ", FALSE); + obstack_1grow (obs, '\0'); + 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); +} + +/* 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 = 0; + + if (bad_argc (argv[0], argc, 1, 2)) + return; + if (argc == 2 && !numeric_arg (argv[0], ARG (1), &exit_code)) + exit_code = 0; + + 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 (no_gnu_extensions) + obstack_grow (obs, ARG (1), strlen (ARG (1))); + else + dump_args (obs, argc, argv, " ", FALSE); + obstack_1grow (obs, '\0'); + push_wrapup (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, const char *data) +{ + SYMBOL_TRACED (sym) = (boolean) (data != NULL); +} + +static void +m4_traceon (struct obstack *obs, int argc, token_data **argv) +{ + symbol *s; + int i; + + if (argc == 1) + hack_all_symbols (set_trace, (char *) obs); + else + for (i = 1; i < argc; i++) + { + s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP); + if (s != NULL) + set_trace (s, (char *) obs); + else + M4ERROR ((warning_status, 0, + "Undefined name %s", TOKEN_DATA_TEXT (argv[i]))); + } +} + +/*------------------------------------------------------------------------. +| 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); + else + M4ERROR ((warning_status, 0, + "Undefined name %s", TOKEN_DATA_TEXT (argv[i]))); + } +} + +/*----------------------------------------------------------------------. +| 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 *cp, *last; + int l1, l2, retval; + + if (bad_argc (argv[0], argc, 3, 3)) + return; + + l1 = strlen (ARG (1)); + l2 = strlen (ARG (2)); + + last = ARG (1) + l1 - l2; + + for (cp = ARG (1); cp <= last; cp++) + { + if (strncmp (cp, ARG (2), l2) == 0) + break; + } + retval = (cp <= last) ? cp - ARG (1) : -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, length, avail; + + if (bad_argc (argv[0], argc, 3, 4)) + 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) +{ + char from; + char to; + + for (from = '\0'; *s != '\0'; from = *s++) + { + if (*s == '-' && from != '\0') + { + to = *++s; + if (to == '\0') + obstack_1grow (obs, '-'); /* trailing dash */ + 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 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) +{ + register const char *data, *tmp; + const char *from, *to; + int tolen; + + if (bad_argc (argv[0], argc, 3, 4)) + return; + + from = ARG (2); + if (strchr (from, '-') != NULL) + { + from = expand_ranges (from, obs); + if (from == NULL) + return; + } + + if (argc == 4) + { + to = ARG (3); + if (strchr (to, '-') != NULL) + { + to = expand_ranges (to, obs); + if (to == NULL) + return; + } + } + else + to = ""; + + tolen = strlen (to); + + for (data = ARG (1); *data; data++) + { + tmp = strchr (from, *data); + if (tmp == NULL) + { + obstack_1grow (obs, *data); + } + else + { + if (tmp - from < tolen) + obstack_1grow (obs, *(to + (tmp - from))); + } + } +} + +/*----------------------------------------------------------------------. +| 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) +{ + 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) +{ + register unsigned 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->end[ch] > 0) + obstack_grow (obs, victim + regs->start[ch], + regs->end[ch] - regs->start[ch]); + break; + + default: + obstack_1grow (obs, ch); + break; + } + } +} + +/*--------------------------------------------------------------------------. +| 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)) + return; + + victim = TOKEN_DATA_TEXT (argv[1]); + regexp = TOKEN_DATA_TEXT (argv[2]); + + buf.buffer = NULL; + buf.allocated = 0; + buf.fastmap = NULL; + buf.translate = NULL; + msg = re_compile_pattern (regexp, strlen (regexp), &buf); + + if (msg != NULL) + { + M4ERROR ((warning_status, 0, + "Bad regular expression: `%s': %s", regexp, msg)); + return; + } + + length = strlen (victim); + startpos = re_search (&buf, victim, length, 0, length, ®s); + xfree (buf.buffer); + + if (startpos == -2) + { + M4ERROR ((warning_status, 0, + "Error matching regular expression \"%s\"", regexp)); + return; + } + + if (argc == 3) + shipout_int (obs, startpos); + else if (startpos >= 0) + { + repl = TOKEN_DATA_TEXT (argv[3]); + substitute (obs, victim, repl, ®s); + } + + return; +} + +/*--------------------------------------------------------------------------. +| 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)) + return; + + regexp = TOKEN_DATA_TEXT (argv[2]); + + buf.buffer = NULL; + buf.allocated = 0; + buf.fastmap = NULL; + buf.translate = NULL; + msg = re_compile_pattern (regexp, strlen (regexp), &buf); + + if (msg != NULL) + { + M4ERROR ((warning_status, 0, + "Bad regular expression `%s': %s", regexp, msg)); + if (buf.buffer != NULL) + xfree (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'); + + xfree (buf.buffer); + return; +} + +/*-------------------------------------------------------------------------. +| 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) +{ + register 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 (*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/builtin.h b/src/builtin.h new file mode 100644 index 00000000..89088513 --- /dev/null +++ b/src/builtin.h @@ -0,0 +1,39 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Declarations for builtin macros. */ + +#ifndef BUILTIN_H +#define BUILTIN_H 1 + +#include <m4.h> + +#define ARG(i) (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "") + +#define DECLARE(name) \ + static void name __P ((struct obstack *, int, token_data **)) + + + +boolean bad_argc (token_data *name, int argc, int min, int max); +const char *skip_space (const char *arg); + +boolean numeric_arg (token_data *macro, const char *arg, int *valuep); +void shipout_int (struct obstack *obs, int val); + +#endif /* BUILTIN_H */ diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 00000000..ad1988d1 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,421 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1991, 1992, 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "m4.h" + +#include <sys/stat.h> + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* 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) + fclose (debug); + debug = fp; + + if (debug != NULL && debug != stdout) + { + if (fstat (fileno (stdout), &stdout_stat) < 0) + return; + if (fstat (fileno (debug), &debug_stat) < 0) + return; + + if (stdout_stat.st_ino == debug_stat.st_ino + && stdout_stat.st_dev == debug_stat.st_dev) + { + if (debug != stderr) + fclose (debug); + 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); +} + +/*-------------------------------------------------------------------------. +| 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. | +`-------------------------------------------------------------------------*/ + +boolean +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; + + 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, "m4 debug: "); + if (debug_level & DEBUG_TRACE_FILE) + fprintf (debug, "%s: ", current_file); + if (debug_level & DEBUG_TRACE_LINE) + fprintf (debug, "%d: ", current_line); +} + +/* 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). | +`---------------------------------------------------------------------*/ + +#if __STDC__ +static void +trace_format (const char *fmt, ...) +#else +static void +trace_format (...) +#endif +{ +#if ! __STDC__ + const char *fmt; +#endif + va_list args; + char ch; + + int d; + char nbuf[32]; + const char *s; + int slen; + int maxlen; + +#if __STDC__ + va_start (args, fmt); +#else + va_start (args); + fmt = va_arg (args, const char *); +#endif + + 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 (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 = 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/eval.c b/src/eval.c new file mode 100644 index 00000000..c6dc85f4 --- /dev/null +++ b/src/eval.c @@ -0,0 +1,774 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, 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 (). */ + +#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 (*eval_text)) + eval_text++; + + last_text = eval_text; + + if (*eval_text == '\0') + return EOTEXT; + + if (isdigit (*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 (*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 (*eval_text)) + digit = *eval_text - '0'; + else if (islower (*eval_text)) + digit = *eval_text - 'a' + 10; + else if (isupper (*eval_text)) + digit = *eval_text - 'A' + 10; + else + break; + + if (digit >= base) + break; + + (*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". | +`---------------------------------------*/ + +boolean +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 (boolean) (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; + + switch (op) + { + case LSHIFT: + *v1 = *v1 << v2; + break; + + case RSHIFT: + *v1 = *v1 >> v2; + 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 + *v1 = *v1 / v2; + break; + + case MODULO: + if (v2 == 0) + return MODULO_ZERO; + 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/evalmp.c b/src/evalmp.c new file mode 100644 index 00000000..5c48b8db --- /dev/null +++ b/src/evalmp.c @@ -0,0 +1,27 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file is used to compile the gmp aware version of eval() */ + +#include "m4.h" + +#ifdef WITH_GMP +#define USE_GMP + +#include "eval.c" +#endif diff --git a/src/format.c b/src/format.c new file mode 100644 index 00000000..f8107c05 --- /dev/null +++ b/src/format.c @@ -0,0 +1,744 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* printf like formatting for m4. */ + +#include "m4.h" + +#ifdef HAVE_EFGCVT + +/* Various constants for floating point formatting. */ +#define MAXFIELD 128 /* size of buffer for formatted text */ +/* The following two are hardware dependant. */ +#define ECVTMAX 18 /* max number of significant digits for %e */ +#define FCVTMAX (18+38+4) /* max number of significant digits for %f */ + +/* Externs used herein. */ +#if HAVE_EFGCVT <= 1 +extern char *ecvt (), *fcvt (), *gcvt (); +#endif + +#ifndef STDC_HEADERS +extern int atoi (); +extern long atol (); +extern double atof (); +#endif /* STDC_HEADERS */ + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static char const digits[] = "0123456789abcdef"; +static char const Digits[] = "0123456789ABCDEF"; + +/* STR has dimension MAXFIELD (?). */ + +static char * +ulong_to_str (register unsigned long val, char *str, int base, + const char *digits) +{ + register char *s = &str[MAXFIELD]; + + *--s = '\0'; + do + { + *--s = digits[val % base]; + val /= base; + } + while (val > 0); + + return s; +} + +/*-----------------------------------------. +| Clear trailing zeroes, return argument. | +`-----------------------------------------*/ + +static char * +clr0 (char *s) +{ + register char *t; + + for (t = s + strlen (s); *--t == '0' && t > s;) + *t = '\0'; + return s; +} + +#endif /* HAVE_EFGCVT */ + +/* 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) +{ +#ifdef HAVE_EFGCVT + + const char *fmt; /* format control string */ + int c; /* a simple character */ + char fc; /* format code */ + + /* Flags. */ + char flags; /* 1 iff treating flags */ + char ljust; /* left justification */ + char mandsign; /* mandatory sign */ + char noplus; /* use space if no sign */ + char alternate; /* use alternate form */ + char zeropad; /* do zero padding */ + char plus; /* plus-sign, according to mandatory and noplus */ + + /* Precision specifiers. */ + int width; /* minimum field width */ + int prec; /* precision */ + int maxch; /* maximum no. of chars to print */ + char lflag; /* long flag */ + char hflag; /* short flag */ + + /* Different parts of each specification. */ + char sign; /* wanted sign, iff any */ + int ppad; /* pre-prefix zero padding */ + const char *prefix; /* value prefix */ + int lpad; /* zero padding on the left */ + register char *s; /* ptr to formatted text */ + int rpad; /* zero padding on the rigth*/ + const char *suffix; /* value suffix */ + + /* Buffer and stuff. */ + char str[MAXFIELD]; /* buffer for formatted text */ + int length; /* length of str */ + int padding; /* padding at the left or rigth */ + register int i; /* an index */ + +/* Length of trailing string in str. */ +#define LENGTH(s) (&str[MAXFIELD-1] - (s)) +#define HAS_SIGN (sign != '\0') + + fmt = ARG_STR (argc, argv); + for (;;) + { + while ((c = *fmt++) != '%') + { + if (c == 0) + return; + obstack_1grow (obs, c); + } + if (*fmt == '%') + { + obstack_1grow (obs, '%'); + fmt++; + continue; + } + + /* Parse flags. */ + flags = 1; + ljust = mandsign = noplus = alternate = zeropad = 0; + do + { + switch (*fmt) + { + case '-': /* left justification */ + ljust = 1; + break; + + case '+': /* mandatory sign */ + mandsign = 1; + break; + + case ' ': /* space instead of positive sign */ + noplus = 1; + break; + + case '0': /* zero padding */ + zeropad = 1; + break; + + case '#': /* alternate output */ + alternate = 1; + break; + + default: + flags = 0; + break; + } + } + while (flags && fmt++); + + plus = '\0'; /* what to use as a plus ??? */ + if (mandsign) + plus = '+'; + else if (noplus) + plus = ' '; + + if (ljust) + zeropad = 0; + + /* Minimum field width. */ + width = -1; + if (*fmt == '*') + { + width = ARG_INT (argc, argv); + fmt++; + } + else if (isdigit (*fmt)) + { + width = 0; + do + { + width = width * 10 + *fmt++ - '0'; + } + while (isdigit (*fmt)); + } + + /* Maximum precision. */ + prec = -1; + if (*fmt == '.') + { + if (*(++fmt) == '*') + { + prec = ARG_INT (argc, argv); + ++fmt; + } + else if (isdigit (*fmt)) + { + prec = 0; + do + { + prec = prec * 10 + *fmt++ - '0'; + } + while (isdigit (*fmt)) + ; + } + } + + /* Length modifiers. */ + lflag = (*fmt == 'l'); + hflag = (*fmt == 'h'); + if (lflag || hflag) + fmt++; + + sign = '\0'; + ppad = lpad = rpad = 0; + maxch = -1; + prefix = suffix = ""; + + switch (fc = *fmt++) + { + + case '\0': + return; + + case 'c': + c = ARG_INT (argc, argv); + str[0] = (unsigned char) c; + str[1] = '\0'; + s = str; + break; + + case 's': + s = ARG_STR (argc, argv); + maxch = prec; + break; + + case 'd': + case 'i': + if (lflag) + { + long val = ARG_LONG (argc, argv); + if (val < 0) + { + val = -val; /* does not work for MINLONG */ + sign = '-'; + } + else + sign = plus; + s = ulong_to_str ((unsigned long) val, str, 10, digits); + } + else + { + int val = ARG_INT (argc, argv); + if (hflag) + val = (short) val; + if (val < 0) + { + val = -val; /* does not work for MININT */ + sign = '-'; + } + else + sign = plus; + s = ulong_to_str ((unsigned long) val, str, 10, digits); + } + if (zeropad) + lpad = width - LENGTH (s) - HAS_SIGN; + break; + + case 'o': + if (lflag) + { + unsigned long val = ARG_ULONG (argc, argv); + s = ulong_to_str ((unsigned long) val, str, 8, digits); + } + else + { + unsigned int val = ARG_UINT (argc, argv); + if (hflag) + val = (unsigned short) val; + s = ulong_to_str ((unsigned long) val, str, 8, digits); + } + if (alternate) + prefix = "0"; + if (zeropad) + lpad = width - LENGTH (s) - alternate; + break; + + case 'x': + case 'X': + if (lflag) + { + unsigned long val = ARG_ULONG (argc, argv); + s = ulong_to_str ((unsigned long) val, str, 16, + (fc == 'x') ? digits : Digits); + } + else + { + unsigned int val = ARG_UINT (argc, argv); + if (hflag) + val = (unsigned short) val; + s = ulong_to_str ((unsigned long) val, str, 16, + (fc == 'x') ? digits : Digits); + } + if (alternate) + prefix = (fc == 'X') ? "0X" : "0x"; + if (zeropad) + lpad = width - LENGTH (s) - 2*alternate; + break; + + case 'u': + if (lflag) + { + unsigned long val = ARG_ULONG (argc, argv); + s = ulong_to_str ((unsigned long) val, str, 10, digits); + } + else + { + unsigned int val = ARG_UINT (argc, argv); + if (hflag) + val = (unsigned short) val; + s = ulong_to_str ((unsigned long) val, str, 10, digits); + } + if (zeropad) + lpad = width - LENGTH (s); + break; + + case 'e': + case 'E': + { + char *t; + int sgn, decpt, exp, n; + double val = ARG_DOUBLE (argc, argv); + + if (prec < 0) + prec = 6; + t = clr0 (ecvt (val, min (prec + 1, ECVTMAX), &decpt, &sgn)); + sign = sgn ? '-' : plus; + + n = prec; + s = str; + exp = (t[0] == '0' && t[1] == '\0') ? 0 : decpt - 1; + + *s++ = *t++; + if (n > 0 || alternate) + *s++ = '.'; + while (*t != '\0' && --n >= 0) + *s++ = *t++; + *s = '\0'; + rpad = n; + + sgn = 0; + if (exp < 0) + { + exp = -exp; + sgn = 1; + } + t = ulong_to_str ((unsigned long) exp, str, 10, digits); + if (exp < 10) + *--t = '0'; /* always at least two digits */ + *--t = sgn ? '-' : '+'; + *--t = fc; + + if (zeropad) + { + lpad = width - HAS_SIGN - (s - str) - LENGTH (t); + if (rpad > 0) + lpad -= rpad; + } + + suffix = t; + s = str; + } + break; + + case 'f': + { + const char *t; + int sgn, decpt, n; + double val = ARG_DOUBLE (argc, argv); + + if (prec < 0) + prec = 6; + + /* FIXME: For the following line, Dave Anglin reports + ``warning: passing arg 1 of `clr0' discards `const' from + pointer target type''. I suspect fcvt might be declared + as returning const on some systems. Pouah! I should + revise this whole module, one of these days... */ + + t = clr0 (fcvt (val, min (prec, FCVTMAX), &decpt, &sgn)); + + sign = sgn ? '-' : plus; + + n = prec; + s = str; + + if (decpt <= 0) + { + prefix = (n > 0 || alternate) ? "0." : "0"; + lpad = min (-decpt, prec); + n -= lpad; + } + else + { + while (--decpt >= 0) + *s++ = *t++; + if (n > 0 || alternate) + *s++ = '.'; + } + while (*t && --n >= 0) + *s++ = *t++; + + *s = '\0'; + rpad = n; + + if (zeropad) + ppad = width - HAS_SIGN - (prefix[1] ? 2 : 1) - lpad - + (s - str) - rpad; + + s = str; + } + break; + + default: + continue; + } + + if (lpad < 0) + lpad = 0; + if (rpad < 0) + rpad = 0; + if (width < 0) + width = 0; + + i = strlen (s); + if (maxch <= 0 || maxch > i) + maxch = i; + + length = (HAS_SIGN + ppad + strlen (prefix) + lpad + maxch + + rpad + strlen (suffix)); + padding = 0; + if (width != 0) + { + padding = width - length; + } + + if (ljust == 0) /* left padding */ + for (i = padding; --i >= 0;) + obstack_1grow (obs, ' '); + if (HAS_SIGN) /* sign */ + obstack_1grow (obs, sign); + for (i = ppad; --i >= 0;) /* pre-prefix zero padding */ + obstack_1grow (obs, '0'); + for (; *prefix; ++prefix) /* prefix */ + obstack_1grow (obs, *prefix); + for (i = lpad; --i >= 0;) /* left zero padding */ + obstack_1grow (obs, '0'); + for (i = maxch; --i >= 0; ++s) /* actual text */ + obstack_1grow (obs, *s); + for (i = rpad; --i >= 0;) /* right zero padding */ + obstack_1grow (obs, '0'); + for (; *suffix; ++suffix) /* suffix */ + obstack_1grow (obs, *suffix); + if (ljust != 0) /* right padding */ + for (i = padding; --i >= 0;) + obstack_1grow (obs, ' '); + } + +#else /* not HAVE_EFGCVT */ + + 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[256]; /* buffer for formatted text */ + enum {INT, UINT, LONG, ULONG, DOUBLE, STR} datatype; + + fmt = 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 (*fmt)) + { + do + { + fmt++; + } + while (isdigit (*fmt)); + } + + /* Maximum precision. */ + prec = -1; + if (*fmt == '.') + { + if (*(++fmt) == '*') + { + prec = ARG_INT (argc, argv); + ++fmt; + } + else if (isdigit (*fmt)) + { + do + { + fmt++; + } + while (isdigit (*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': + datatype = DOUBLE; + break; + + default: + continue; + } + + c = *fmt; + *fmt = '\0'; + + switch(datatype) + { + case INT: + if (width != -1 && prec != -1) + sprintf (str, fstart, width, prec, ARG_INT(argc, argv)); + else if (width != -1) + sprintf (str, fstart, width, ARG_INT(argc, argv)); + else if (prec != -1) + sprintf (str, fstart, prec, ARG_INT(argc, argv)); + else + sprintf (str, fstart, ARG_INT(argc, argv)); + break; + + case UINT: + if (width != -1 && prec != -1) + sprintf (str, fstart, width, prec, ARG_UINT(argc, argv)); + else if (width != -1) + sprintf (str, fstart, width, ARG_UINT(argc, argv)); + else if (prec != -1) + sprintf (str, fstart, prec, ARG_UINT(argc, argv)); + else + sprintf (str, fstart, ARG_UINT(argc, argv)); + break; + + case LONG: + if (width != -1 && prec != -1) + sprintf (str, fstart, width, prec, ARG_LONG(argc, argv)); + else if (width != -1) + sprintf (str, fstart, width, ARG_LONG(argc, argv)); + else if (prec != -1) + sprintf (str, fstart, prec, ARG_LONG(argc, argv)); + else + sprintf (str, fstart, ARG_LONG(argc, argv)); + break; + + case ULONG: + if (width != -1 && prec != -1) + sprintf (str, fstart, width, prec, ARG_ULONG(argc, argv)); + else if (width != -1) + sprintf (str, fstart, width, ARG_ULONG(argc, argv)); + else if (prec != -1) + sprintf (str, fstart, prec, ARG_ULONG(argc, argv)); + else + sprintf (str, fstart, ARG_ULONG(argc, argv)); + break; + + case DOUBLE: + if (width != -1 && prec != -1) + sprintf (str, fstart, width, prec, ARG_DOUBLE(argc, argv)); + else if (width != -1) + sprintf (str, fstart, width, ARG_DOUBLE(argc, argv)); + else if (prec != -1) + sprintf (str, fstart, prec, ARG_DOUBLE(argc, argv)); + else + sprintf (str, fstart, ARG_DOUBLE(argc, argv)); + break; + + case STR: + if (width != -1 && prec != -1) + sprintf (str, fstart, width, prec, ARG_STR(argc, argv)); + else if (width != -1) + sprintf (str, fstart, width, ARG_STR(argc, argv)); + else if (prec != -1) + sprintf (str, fstart, prec, ARG_STR(argc, argv)); + else + sprintf (str, fstart, ARG_STR(argc, argv)); + break; + } + + *fmt = c; + + obstack_grow (obs, str, strlen (str)); + } + +#endif /* not HAVE_EFGCVT */ +} diff --git a/src/freeze.c b/src/freeze.c new file mode 100644 index 00000000..f17baff9 --- /dev/null +++ b/src/freeze.c @@ -0,0 +1,369 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, 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, "w"), !file) + { + M4ERROR ((warning_status, errno, name)); + return; + } + + /* Write a recognizable header. */ + + fprintf (file, "# This is a frozen state file generated by GNU %s %s\n", + PRODUCT, VERSION); + 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: Built-in 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); + fclose (file); +} + +/*----------------------------------------------------------------------. +| 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) + + file = path_search (name); + if (file == NULL) + M4ERROR ((EXIT_FAILURE, errno, "Cannot open %s", name)); + + allocated[0] = 100; + string[0] = xmalloc ((size_t) allocated[0]); + allocated[1] = 100; + string[1] = xmalloc ((size_t) allocated[1]); + + while (GET_CHARACTER, character != EOF) + switch (character) + { + default: + M4ERROR ((EXIT_FAILURE, 0, "Ill-formated frozen file")); + + case '\n': + + /* Skip empty lines. */ + + break; + + case '#': + + /* Comments are introduced by `#' at beginning of line, and are + ignored. */ + + while (character != EOF && character != '\n') + GET_CHARACTER; + VALIDATE ('\n'); + break; + + 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] = xmalloc ((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] = xmalloc ((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]); + if (bp) + define_builtin (string[0], bp, SYMBOL_PUSHDEF, 0); + else + M4ERROR ((warning_status, 0, "\ +`%s' from frozen file not found in builtin table!", + string[0])); + 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; + + case 'V': + + /* Validate format version. Only `1' is acceptable for now. */ + + GET_CHARACTER; + VALIDATE ('1'); + GET_CHARACTER; + VALIDATE ('\n'); + break; + + } + + free (string[0]); + free (string[1]); + fclose (file); + +#undef GET_CHARACTER +#undef GET_NUMBER +#undef VALIDATE +} diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 00000000..efd82235 --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,1051 @@ +/* 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, 97, 98, 99 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. 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. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include <gnu-versions.h> +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include <stdlib.h> +# include <unistd.h> +#endif /* GNU C library. */ + +#ifdef VMS +# include <unixlib.h> +# if HAVE_STRING_H - 0 +# include <string.h> +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' 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. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the 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.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; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_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. */ + +static char *nextchar; + +/* 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 = '?'; + +/* 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. + + 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. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include <string.h> +# define my_index strchr +#else + +# if HAVE_STRING_H +# include <string.h> +# else +# include <strings.h> +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* 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. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* 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). */ + original_argc = argc; + original_argv = argv; +} +# ifdef text_set_element +text_set_element (__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#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. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = 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. */ + +#ifdef _LIBC + /* 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 (nonoption_flags_len > 0 && top >= 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) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + 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. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* 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. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + 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. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + 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. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_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. */ +#ifdef _LIBC +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *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 (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = 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 (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + 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 (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = 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 (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[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[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[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 = 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, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - 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 + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + 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) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (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[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + 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 (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = 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, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - 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 (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + 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) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + 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 (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + 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/getopt.h b/src/getopt.h new file mode 100644 index 00000000..12b7ad56 --- /dev/null +++ b/src/getopt.h @@ -0,0 +1,180 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#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 <features.h>, but + that does not exist if we are standalone. So: if __GNU_LIBRARY__ is + not defined, include <ctype.h>, which will pull in <features.h> 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 <ctype.h> +#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 +{ +# if defined __STDC__ && __STDC__ + const char *name; +# else + char *name; +# endif + /* 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 '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __STDC__ && __STDC__ +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int __argc, char *const *__argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/src/getopt1.c b/src/getopt1.c new file mode 100644 index 00000000..3d264f2d --- /dev/null +++ b/src/getopt1.c @@ -0,0 +1,188 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "getopt.h" + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. 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. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* 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 (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + 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/input.c b/src/input.c new file mode 100644 index 00000000..8916fd3f --- /dev/null +++ b/src/input.c @@ -0,0 +1,852 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, 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 "input_stack". 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 "input_stack" is empty), input is switched + over to "wrapup_stack". To make this easier, all references to the + current input stack, whether it be "input_stack" or "wrapup_stack", + are done through a pointer "current_input", which points to either + "input_stack" or "wrapup_stack". + + 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. Whenever a file + input_block is pushed, the current file name and line number is saved + in the input_block, and the two variables are reset to match the new + input file. */ + +#ifdef ENABLE_CHANGEWORD +#include "regex.h" +#endif + +enum input_type +{ + INPUT_FILE, + INPUT_STRING, + INPUT_MACRO +}; + +typedef enum input_type input_type; + +struct input_block +{ + struct input_block *prev; /* previous input_block on the input stack */ + input_type type; /* INPUT_FILE, INPUT_STRING or INPUT_MACRO */ + union + { + struct + { + char *string; /* string value */ + } + u_s; + struct + { + FILE *file; /* input file handle */ + const char *name; /* name of PREVIOUS input file */ + int lineno; /* current line number for do */ + /* Yet another attack of "The curse of global variables" (sic) */ + int out_lineno; /* current output line number do */ + boolean advance_line; /* start_of_input_line from next_char () */ + } + u_f; + struct + { + builtin_func *func; /* pointer to macros function */ + boolean traced; /* TRUE iff builtin is traced */ + } + u_m; + } + 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; + +/* Normal input stack. */ +static struct obstack input_stack; + +/* Wrapup input stack. */ +static struct obstack wrapup_stack; + +/* Input or wrapup. */ +static struct obstack *current_input; + +/* Bottom of token_stack, for obstack_free. */ +static char *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 boolean start_of_input_line; + +#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; + +#endif /* ENABLE_CHANGEWORD */ + + +/*-------------------------------------------------------------------------. +| 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 are consequentely released. | +`-------------------------------------------------------------------------*/ + +void +push_file (FILE *fp, const char *title) +{ + 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->u.u_f.name = current_file; + i->u.u_f.lineno = current_line; + i->u.u_f.out_lineno = output_current_line; + i->u.u_f.advance_line = start_of_input_line; + current_file = obstack_copy0 (current_input, title, strlen (title)); + current_line = 1; + output_current_line = -1; + + i->u.u_f.file = fp; + i->prev = isp; + isp = i; +} + +/*-------------------------------------------------------------------------. +| push_macro () pushes a builtin macros definition on the input stack. If | +| next is non-NULL, this push invalidates a call to push_string_init (), | +| whose storage are consequentely released. | +`-------------------------------------------------------------------------*/ + +void +push_macro (builtin_func *func, boolean traced) +{ + 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->u.u_m.func = func; + i->u.u_m.traced = traced; + 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; + 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 = obstack_finish (current_input); + next->prev = isp; + isp = next; + ret = isp->u.u_s.string; /* for immediate use only */ + } + 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 | +| he 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 = (input_block *) obstack_alloc (&wrapup_stack, + sizeof (struct input_block)); + i->prev = wsp; + i->type = INPUT_STRING; + i->u.u_s.string = 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) + DEBUG_MESSAGE2 ("input reverted to %s, line %d", + isp->u.u_f.name, isp->u.u_f.lineno); + + fclose (isp->u.u_f.file); + current_file = isp->u.u_f.name; + current_line = isp->u.u_f.lineno; + output_current_line = isp->u.u_f.out_lineno; + start_of_input_line = isp->u.u_f.advance_line; + if (tmp != NULL) + 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; +} + +/*------------------------------------------------------------------------. +| 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. | +`------------------------------------------------------------------------*/ + +boolean +pop_wrapup (void) +{ + if (wsp == NULL) + return FALSE; + + current_input = &wrapup_stack; + isp = wsp; + wsp = NULL; + + 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.u_m.func; + TOKEN_DATA_FUNC_TRACED (td) = isp->u.u_m.traced; +} + + +/*------------------------------------------------------------------------. +| 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. | +`------------------------------------------------------------------------*/ + +int +peek_input (void) +{ + register int ch; + + while (1) + { + if (isp == NULL) + return CHAR_EOF; + + switch (isp->type) + { + case INPUT_STRING: + ch = isp->u.u_s.string[0]; + if (ch != '\0') + return ch; + break; + + case INPUT_FILE: + ch = getc (isp->u.u_f.file); + if (ch != EOF) + { + ungetc (ch, isp->u.u_f.file); + return ch; + } + break; + + case INPUT_MACRO: + return CHAR_MACRO; + + default: + M4ERROR ((warning_status, 0, + "INTERNAL ERROR: Input stack botch in peek_input ()")); + abort (); + } + /* End of input source --- pop one level. */ + pop_input (); + } +} + +/*-------------------------------------------------------------------------. +| 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. | +`-------------------------------------------------------------------------*/ + +static int +next_char (void) +{ + register int ch; + + if (start_of_input_line) + { + start_of_input_line = FALSE; + current_line++; + } + + while (1) + { + if (isp == NULL) + return CHAR_EOF; + + switch (isp->type) + { + case INPUT_STRING: + ch = *isp->u.u_s.string++; + if (ch != '\0') + return ch; + break; + + case INPUT_FILE: + ch = getc (isp->u.u_f.file); + 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; + + while ((ch = next_char ()) != CHAR_EOF && ch != '\n') + ; +} + + +/*----------------------------------------------------------------------. +| This function is for matching a string against a prefix of the input | +| stream. If the string matches the input, the input is discarded, | +| otherwise the characters read are pushed back again. The function is | +| used only when multicharacter quotes or comment delimiters are used. | +`----------------------------------------------------------------------*/ + +static int +match_input (const char *s) +{ + int n; /* number of characters matched */ + int ch; /* input character */ + const char *t; + + ch = peek_input (); + if (ch != *s) + return 0; /* fail */ + (void) next_char (); + + if (s[1] == '\0') + return 1; /* short match */ + + for (n = 1, t = s++; (ch = peek_input ()) == *s++; n++) + { + (void) next_char (); + if (*s == '\0') /* long match */ + return 1; + } + + /* Failed, push back input. */ + obstack_grow (push_string_init (), t, n); + push_string_finish (); + return 0; +} + +/*------------------------------------------------------------------------. +| The macro MATCH() is used to match a string 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. | +`------------------------------------------------------------------------*/ + +#define MATCH(ch, s) \ + ((s)[0] == (ch) \ + && (ch) != '\0' \ + && ((s)[1] == '\0' \ + || (match_input ((s) + 1) ? (ch) = peek_input (), 1 : 0))) + + +/*----------------------------------------------------------. +| Inititialise input stacks, and quote/comment characters. | +`----------------------------------------------------------*/ + +void +input_init (void) +{ + current_file = "NONE"; + current_line = 0; + + obstack_init (&token_stack); + obstack_init (&input_stack); + obstack_init (&wrapup_stack); + + current_input = &input_stack; + + obstack_1grow (&token_stack, '\0'); + token_bottom = obstack_finish (&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 + if (user_word_regexp) + set_word_regexp (user_word_regexp); + else + set_word_regexp (DEFAULT_WORD_REGEXP); +#endif +} + + +/*--------------------------------------------------------------. +| Functions for setting quotes and comment delimiters. Used by | +| m4_changecom () and m4_changequote (). | +`--------------------------------------------------------------*/ + +void +set_quotes (const char *lq, const char *rq) +{ + xfree (lquote.string); + xfree (rquote.string); + + lquote.string = xstrdup (lq ? lq : DEF_LQUOTE); + lquote.length = strlen (lquote.string); + rquote.string = xstrdup (rq ? rq : DEF_RQUOTE); + rquote.length = strlen (rquote.string); +} + +void +set_comment (const char *bc, const char *ec) +{ + xfree (bcomm.string); + xfree (ecomm.string); + + bcomm.string = xstrdup (bc ? bc : DEF_BCOMM); + bcomm.length = strlen (bcomm.string); + ecomm.string = xstrdup (ec ? ec : DEF_ECOMM); + ecomm.length = strlen (ecomm.string); +} + +#ifdef ENABLE_CHANGEWORD + +void +set_word_regexp (const char *regexp) +{ + int i; + char test[2]; + const char *msg; + + if (!strcmp (regexp, DEFAULT_WORD_REGEXP)) + { + default_word_regexp = TRUE; + return; + } + + default_word_regexp = FALSE; + + msg = re_compile_pattern (regexp, strlen (regexp), &word_regexp); + + if (msg != NULL) + { + M4ERROR ((warning_status, 0, + "Bad regular expression `%s': %s", regexp, msg)); + return; + } + + if (word_start == NULL) + word_start = xmalloc (256); + + word_start[0] = '\0'; + test[1] = '\0'; + for (i = 1; i < 256; i++) + { + test[0] = i; + if (re_search (&word_regexp, test, 1, 0, 0, ®s) >= 0) + strcat (word_start, test); + } +} + +#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 = 0; +#endif + + obstack_free (&token_stack, token_bottom); + obstack_1grow (&token_stack, '\0'); + token_bottom = obstack_finish (&token_stack); + + ch = peek_input (); + if (ch == CHAR_EOF) + { + return TOKEN_EOF; +#ifdef DEBUG_INPUT + fprintf (stderr, "next_token -> EOF\n"); +#endif + } + if (ch == CHAR_MACRO) + { + init_macro_token (td); + (void) next_char (); + return TOKEN_MACDEF; + } + + (void) next_char (); + if (MATCH (ch, bcomm.string)) + { + obstack_grow (&token_stack, bcomm.string, bcomm.length); + while ((ch = next_char ()) != CHAR_EOF && !MATCH (ch, ecomm.string)) + obstack_1grow (&token_stack, ch); + if (ch != CHAR_EOF) + obstack_grow (&token_stack, ecomm.string, ecomm.length); + type = TOKEN_STRING; + } +#ifdef ENABLE_CHANGEWORD + else if (default_word_regexp && (isalpha (ch) || ch == '_')) +#else + else if (isalpha (ch) || ch == '_') +#endif + { + 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 && strchr (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, 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 = 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)) + { + type = TOKEN_SIMPLE; + obstack_1grow (&token_stack, ch); + } + else + { + quote_level = 1; + while (1) + { + ch = next_char (); + if (ch == CHAR_EOF) + M4ERROR ((EXIT_FAILURE, 0, + "ERROR: EOF in string")); + + if (MATCH (ch, rquote.string)) + { + if (--quote_level == 0) + break; + obstack_grow (&token_stack, rquote.string, rquote.length); + } + else if (MATCH (ch, lquote.string)) + { + 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) = 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 -> %d (%s)\n", type, TOKEN_DATA_TEXT (td)); +#endif + return type; +} + + +#ifdef DEBUG_INPUT + +static void +print_token (const char *s, token_type t, token_data *td) +{ + fprintf (stderr, "%s: ", s); + switch (t) + { /* TOKSW */ + 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: 0x%x\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 +lex_debug (void) +{ + token_type t; + token_data td; + + while ((t = next_token (&td)) != NULL) + print_token ("lex", t, &td); +} +#endif diff --git a/src/ltdl.c b/src/ltdl.c new file mode 100644 index 00000000..9cb5887e --- /dev/null +++ b/src/ltdl.c @@ -0,0 +1,1691 @@ +/* ltdl.c -- system independent dlopen wrapper + Copyright (C) 1998-2000 Free Software Foundation, Inc. + Originally by Thomas Tanner <tanner@ffii.org> + This file is part of GNU Libtool. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Library General Public License, +if you distribute this file as part of a program that uses GNU libtool +to create libraries and programs, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA +*/ + +#define _LTDL_COMPILE_ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#if HAVE_STRING_H +#include <string.h> +#endif + +#if HAVE_STRINGS_H +#include <strings.h> +#endif + +#if HAVE_CTYPE_H +#include <ctype.h> +#endif + +#if HAVE_MALLOC_H +#include <malloc.h> +#endif + +#if HAVE_MEMORY_H +#include <memory.h> +#endif + +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#if HAVE_STDIO_H +#include <stdio.h> +#endif + +#include "ltdl.h" + +#ifdef DLL_EXPORT +# define LTDL_GLOBAL_DATA __declspec(dllexport) +#else +# define LTDL_GLOBAL_DATA +#endif + +/* max. filename length */ +#ifndef LTDL_FILENAME_MAX +#define LTDL_FILENAME_MAX 1024 +#endif + +#undef LTDL_READTEXT_MODE +/* fopen() mode flags for reading a text file */ +#ifdef _WIN32 +#define LTDL_READTEXT_MODE "rt" +#else +#define LTDL_READTEXT_MODE "r" +#endif + +#undef LTDL_SYMBOL_LENGTH +/* This is the maximum symbol size that won't require malloc/free */ +#define LTDL_SYMBOL_LENGTH 128 + +#undef LTDL_SYMBOL_OVERHEAD +/* This accounts for the _LTX_ separator */ +#define LTDL_SYMBOL_OVERHEAD 5 + +static const char objdir[] = LTDL_OBJDIR; +#ifdef LTDL_SHLIB_EXT +static const char shlib_ext[] = LTDL_SHLIB_EXT; +#endif + +static const char unknown_error[] = "unknown error"; +static const char dlopen_not_supported_error[] = "dlopen support not available"; +static const char file_not_found_error[] = "file not found"; +static const char no_symbols_error[] = "no symbols defined"; +static const char cannot_open_error[] = "can't open the module"; +static const char cannot_close_error[] = "can't close the module"; +static const char symbol_error[] = "symbol not found"; +static const char memory_error[] = "not enough memory"; +static const char invalid_handle_error[] = "invalid handle"; +static const char buffer_overflow_error[] = "internal buffer overflow"; +static const char shutdown_error[] = "library already shutdown"; + +#ifndef HAVE_PRELOADED_SYMBOLS +/* If libtool won't define it, we'd better do */ +LTDL_GLOBAL_DATA const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } }; +#endif + +static const char *last_error = 0; + +LTDL_GLOBAL_DATA lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc; +LTDL_GLOBAL_DATA void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free; + +typedef struct lt_dltype_t { + struct lt_dltype_t *next; + const char *sym_prefix; /* prefix for symbols */ + int (*mod_init) LTDL_PARAMS((void)); + int (*mod_exit) LTDL_PARAMS((void)); + int (*lib_open) LTDL_PARAMS((lt_dlhandle handle, const char *filename)); + int (*lib_close) LTDL_PARAMS((lt_dlhandle handle)); + lt_ptr_t (*find_sym) LTDL_PARAMS((lt_dlhandle handle, const char *symbol)); +} lt_dltype_t; + +#define LTDL_TYPE_TOP 0 + +typedef struct lt_dlhandle_t { + struct lt_dlhandle_t *next; + lt_dltype_t *type; /* dlopening interface */ + lt_dlinfo info; + int depcount; /* number of dependencies */ + lt_dlhandle *deplibs; /* dependencies */ + lt_ptr_t handle; /* system handle */ + lt_ptr_t system; /* system specific data */ + lt_ptr_t app_private; /* application private data */ +} lt_dlhandle_t; + +#undef strdup +#define strdup xstrdup + +static inline char * +strdup(str) + const char *str; +{ + char *tmp; + + if (!str) + return 0; + tmp = (char*) lt_dlmalloc(strlen(str)+1); + if (tmp) + strcpy(tmp, str); + return tmp; +} + +#if ! HAVE_STRCHR + +# if HAVE_INDEX + +# define strchr index + +# else + +# define strchr xstrchr + +static inline const char* +strchr(str, ch) + const char *str; + int ch; +{ + const char *p; + + for (p = str; *p != (char)ch && *p != '\0'; p++) + /*NOWORK*/; + + return (*p == (char)ch) ? p : 0; +} + +# endif + +#endif + +#if ! HAVE_STRRCHR + +# if HAVE_RINDEX + +# define strrchr rindex + +# else + +# define strrchr xstrrchr + +static inline const char* +strrchr(str, ch) + const char *str; + int ch; +{ + const char *p; + + for (p = str; *p != '\0'; p++) + /*NOWORK*/; + + while (*p != (char)ch && p >= str) + p--; + + return (*p == (char)ch) ? p : 0; +} + +# endif + +#endif + +#if HAVE_LIBDL + +/* dynamic linking with dlopen/dlsym */ + +#if HAVE_DLFCN_H +# include <dlfcn.h> +#endif + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +static int +sys_dl_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dl_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dl_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW); + if (!handle->handle) { +#if HAVE_DLERROR + last_error = dlerror(); +#else + last_error = cannot_open_error; +#endif + return 1; + } + return 0; +} + +static int +sys_dl_close (handle) + lt_dlhandle handle; +{ + if (dlclose(handle->handle) != 0) { +#if HAVE_DLERROR + last_error = dlerror(); +#else + last_error = cannot_close_error; +#endif + return 1; + } + return 0; +} + +static lt_ptr_t +sys_dl_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = dlsym(handle->handle, symbol); + + if (!address) +#if HAVE_DLERROR + last_error = dlerror(); +#else + last_error = symbol_error; +#endif + return address; +} + +static +lt_dltype_t +#ifdef NEED_USCORE +sys_dl = { LTDL_TYPE_TOP, "_", sys_dl_init, sys_dl_exit, + sys_dl_open, sys_dl_close, sys_dl_sym }; +#else +sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit, + sys_dl_open, sys_dl_close, sys_dl_sym }; +#endif + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_dl + +#endif + +#if HAVE_SHL_LOAD + +/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ + +#ifdef HAVE_DL_H +#include <dl.h> +#endif + +/* some flags are missing on some systems, so we provide + * harmless defaults. + * + * Mandatory: + * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. + * BIND_DEFERRED - Delay code symbol resolution until actual reference. + * + * Optionally: + * BIND_FIRST - Place the library at the head of the symbol search order. + * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all unsatisfied + * symbols as fatal. This flag allows binding of unsatisfied code + * symbols to be deferred until use. + * [Perl: For certain libraries, like DCE, deferred binding often + * causes run time problems. Adding BIND_NONFATAL to BIND_IMMEDIATE + * still allows unresolved references in situations like this.] + * BIND_NOSTART - Do not call the initializer for the shared library when the + * library is loaded, nor on a future call to shl_unload(). + * BIND_VERBOSE - Print verbose messages concerning possible unsatisfied symbols. + * + * hp9000s700/hp9000s800: + * BIND_RESTRICTED - Restrict symbols visible by the library to those present at + * library load time. + * DYNAMIC_PATH - Allow the loader to dynamically search for the library specified + * by the path argument. + */ + +#ifndef DYNAMIC_PATH +#define DYNAMIC_PATH 0 +#endif /* DYNAMIC_PATH */ +#ifndef BIND_RESTRICTED +#define BIND_RESTRICTED 0 +#endif /* BIND_RESTRICTED */ + +#define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) + +static int +sys_shl_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_shl_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_shl_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = shl_load(filename, LTDL_BIND_FLAGS, 0L); + if (!handle->handle) { + last_error = cannot_open_error; + return 1; + } + return 0; +} + +static int +sys_shl_close (handle) + lt_dlhandle handle; +{ + if (shl_unload((shl_t) (handle->handle)) != 0) { + last_error = cannot_close_error; + return 1; + } + return 0; +} + +static lt_ptr_t +sys_shl_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address; + + if (handle->handle && shl_findsym((shl_t*) &(handle->handle), + symbol, TYPE_UNDEFINED, &address) == 0) + if (address) + return address; + last_error = symbol_error; + return 0; +} + +static +lt_dltype_t +sys_shl = { LTDL_TYPE_TOP, 0, sys_shl_init, sys_shl_exit, + sys_shl_open, sys_shl_close, sys_shl_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_shl + +#endif + +#if HAVE_DLD + +/* dynamic linking with dld */ + +#if HAVE_DLD_H +#include <dld.h> +#endif + +static int +sys_dld_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dld_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_dld_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + handle->handle = strdup(filename); + if (!handle->handle) { + last_error = memory_error; + return 1; + } + if (dld_link(filename) != 0) { + last_error = cannot_open_error; + lt_dlfree(handle->handle); + return 1; + } + return 0; +} + +static int +sys_dld_close (handle) + lt_dlhandle handle; +{ + if (dld_unlink_by_file((char*)(handle->handle), 1) != 0) { + last_error = cannot_close_error; + return 1; + } + lt_dlfree(handle->filename); + return 0; +} + +static lt_ptr_t +sys_dld_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = dld_get_func(symbol); + + if (!address) + last_error = symbol_error; + return address; +} + +static +lt_dltype_t +sys_dld = { LTDL_TYPE_TOP, 0, sys_dld_init, sys_dld_exit, + sys_dld_open, sys_dld_close, sys_dld_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_dld + +#endif + +#ifdef _WIN32 + +/* dynamic linking for Win32 */ + +#include <windows.h> + +static int +sys_wll_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_wll_exit LTDL_PARAMS((void)) +{ + return 0; +} + +/* Forward declaration; required to implement handle search below. */ +static lt_dlhandle handles; + +static int +sys_wll_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + lt_dlhandle cur; + char *searchname = NULL; + char *ext = strrchr(filename, '.'); + + if (ext) { + /* FILENAME already has an extension. */ + searchname = strdup(filename); + } else { + /* Append a `.' to stop Windows from adding an + implicit `.dll' extension. */ + searchname = (char*)lt_dlmalloc(2+ strlen(filename)); + strcpy(searchname, filename); + strcat(searchname, "."); + } + + handle->handle = LoadLibrary(searchname); + lt_dlfree(searchname); + + /* libltdl expects this function to fail if it is unable + to physically load the library. Sadly, LoadLibrary + will search the loaded libraries for a match and return + one of them if the path search load fails. + + We check whether LoadLibrary is returning a handle to + an already loaded module, and simulate failure if we + find one. */ + cur = handles; + while (cur) { + if (!cur->handle) { + cur = 0; + break; + } + if (cur->handle == handle->handle) + break; + cur = cur->next; + } + + if (cur || !handle->handle) { + last_error = cannot_open_error; + return 1; + } + + return 0; +} + +static int +sys_wll_close (handle) + lt_dlhandle handle; +{ + if (FreeLibrary(handle->handle) == 0) { + last_error = cannot_close_error; + return 1; + } + return 0; +} + +static lt_ptr_t +sys_wll_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = GetProcAddress(handle->handle, symbol); + + if (!address) + last_error = symbol_error; + return address; +} + +static +lt_dltype_t +sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit, + sys_wll_open, sys_wll_close, sys_wll_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_wll + +#endif + +#ifdef __BEOS__ + +/* dynamic linking for BeOS */ + +#include <kernel/image.h> + +static int +sys_bedl_init LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_bedl_exit LTDL_PARAMS((void)) +{ + return 0; +} + +static int +sys_bedl_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + image_id image = 0; + + if (filename) { + image = load_add_on(filename); + } else { + image_info info; + int32 cookie = 0; + if (get_next_image_info(0, &cookie, &info) == B_OK) + image = load_add_on(info.name); + } + if (image <= 0) { + last_error = cannot_open_error; + return 1; + } + handle->handle = (void*) image; + return 0; +} + +static int +sys_bedl_close (handle) + lt_dlhandle handle; +{ + if (unload_add_on((image_id)handle->handle) != B_OK) { + last_error = cannot_close_error; + return 1; + } + return 0; +} + +static lt_ptr_t +sys_bedl_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_ptr_t address = 0; + image_id image = (image_id)handle->handle; + + if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY, + &address) != B_OK) { + last_error = symbol_error; + return 0; + } + return address; +} + +static +lt_dltype_t +sys_bedl = { LTDL_TYPE_TOP, 0, sys_bedl_init, sys_bedl_exit, + sys_bedl_open, sys_bedl_close, sys_bedl_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &sys_bedl + +#endif + +/* emulate dynamic linking using preloaded_symbols */ + +typedef struct lt_dlsymlists_t { + struct lt_dlsymlists_t *next; + const lt_dlsymlist *syms; +} lt_dlsymlists_t; + +static const lt_dlsymlist *default_preloaded_symbols = 0; +static lt_dlsymlists_t *preloaded_symbols = 0; + +static int +presym_init LTDL_PARAMS((void)) +{ + preloaded_symbols = 0; + if (default_preloaded_symbols) + return lt_dlpreload(default_preloaded_symbols); + return 0; +} + +static int +presym_free_symlists LTDL_PARAMS((void)) +{ + lt_dlsymlists_t *lists = preloaded_symbols; + + while (lists) { + lt_dlsymlists_t *tmp = lists; + + lists = lists->next; + lt_dlfree(tmp); + } + preloaded_symbols = 0; + return 0; +} + +static int +presym_exit LTDL_PARAMS((void)) +{ + presym_free_symlists(); + return 0; +} + +static int +presym_add_symlist (preloaded) + const lt_dlsymlist *preloaded; +{ + lt_dlsymlists_t *tmp; + lt_dlsymlists_t *lists = preloaded_symbols; + + while (lists) { + if (lists->syms == preloaded) + return 0; + lists = lists->next; + } + + tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t)); + if (!tmp) { + last_error = memory_error; + return 1; + } + tmp->syms = preloaded; + tmp->next = 0; + if (!preloaded_symbols) + preloaded_symbols = tmp; + else { + /* append to the end */ + lists = preloaded_symbols; + while (lists->next) + lists = lists->next; + lists->next = tmp; + } + return 0; +} + +static int +presym_open (handle, filename) + lt_dlhandle handle; + const char *filename; +{ + lt_dlsymlists_t *lists = preloaded_symbols; + + if (!lists) { + last_error = no_symbols_error; + return 1; + } + if (!filename) + filename = "@PROGRAM@"; + while (lists) { + const lt_dlsymlist *syms = lists->syms; + + while (syms->name) { + if (!syms->address && + strcmp(syms->name, filename) == 0) { + handle->handle = (lt_ptr_t) syms; + return 0; + } + syms++; + } + lists = lists->next; + } + last_error = file_not_found_error; + return 1; +} + +static int +presym_close (handle) + lt_dlhandle handle; +{ + /* Just to silence gcc -Wall */ + handle = 0; + return 0; +} + +static lt_ptr_t +presym_sym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + lt_dlsymlist *syms = (lt_dlsymlist*)(handle->handle); + + syms++; + while (syms->address) { + if (strcmp(syms->name, symbol) == 0) + return syms->address; + syms++; + } + last_error = symbol_error; + return 0; +} + +static +lt_dltype_t +presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit, + presym_open, presym_close, presym_sym }; + +#undef LTDL_TYPE_TOP +#define LTDL_TYPE_TOP &presym + +static char *user_search_path = 0; +static lt_dlhandle handles = 0; +static int initialized = 0; + +static lt_dltype_t *types = LTDL_TYPE_TOP; +#undef LTDL_TYPE_TOP + +int +lt_dlinit LTDL_PARAMS((void)) +{ + /* initialize libltdl */ + lt_dltype_t **type = &types; + int typecount = 0; + + if (initialized) { /* Initialize only at first call. */ + initialized++; + return 0; + } + handles = 0; + user_search_path = 0; /* empty search path */ + + while (*type) { + if ((*type)->mod_init()) + *type = (*type)->next; /* Remove it from the list */ + else { + type = &(*type)->next; /* Keep it */ + typecount++; + } + } + if (typecount == 0) { + last_error = dlopen_not_supported_error; + return 1; + } + last_error = 0; + initialized = 1; + return 0; +} + +int +lt_dlpreload (preloaded) + const lt_dlsymlist *preloaded; +{ + if (preloaded) + return presym_add_symlist(preloaded); + presym_free_symlists(); + if (default_preloaded_symbols) + return lt_dlpreload(default_preloaded_symbols); + return 0; +} + +int +lt_dlpreload_default (preloaded) + const lt_dlsymlist *preloaded; +{ + default_preloaded_symbols = preloaded; + return 0; +} + +int +lt_dlexit LTDL_PARAMS((void)) +{ + /* shut down libltdl */ + lt_dltype_t *type = types; + int errors; + + if (!initialized) { + last_error = shutdown_error; + return 1; + } + if (initialized != 1) { /* shut down only at last call. */ + initialized--; + return 0; + } + /* close all modules */ + errors = 0; + while (handles) { + /* FIXME: what if a module depends on another one? */ + if (lt_dlclose(handles)) + errors++; + } + initialized = 0; + while (type) { + if (type->mod_exit()) + errors++; + type = type->next; + } + return errors; +} + +static int +tryall_dlopen (handle, filename) + lt_dlhandle *handle; + const char *filename; +{ + lt_dlhandle cur; + lt_dltype_t *type = types; + const char *saved_error = last_error; + + /* check whether the module was already opened */ + cur = handles; + while (cur) { + /* try to dlopen the program itself? */ + if (!cur->info.filename && !filename) + break; + if (cur->info.filename && filename && + strcmp(cur->info.filename, filename) == 0) + break; + cur = cur->next; + } + if (cur) { + cur->info.ref_count++; + *handle = cur; + return 0; + } + + cur = *handle; + if (filename) { + cur->info.filename = strdup(filename); + if (!cur->info.filename) { + last_error = memory_error; + return 1; + } + } else + cur->info.filename = 0; + while (type) { + if (type->lib_open(cur, filename) == 0) + break; + type = type->next; + } + if (!type) { + if (cur->info.filename) + lt_dlfree(cur->info.filename); + return 1; + } + cur->type = type; + last_error = saved_error; + return 0; +} + +static int +find_module (handle, dir, libdir, dlname, old_name, installed) + lt_dlhandle *handle; + const char *dir; + const char *libdir; + const char *dlname; + const char *old_name; + int installed; +{ + int error; + char *filename; + /* try to open the old library first; if it was dlpreopened, + we want the preopened version of it, even if a dlopenable + module is available */ + if (old_name && tryall_dlopen(handle, old_name) == 0) + return 0; + /* try to open the dynamic library */ + if (dlname) { + /* try to open the installed module */ + if (installed && libdir) { + filename = (char*) + lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1); + if (!filename) { + last_error = memory_error; + return 1; + } + sprintf (filename, "%s/%s", libdir, dlname); + error = tryall_dlopen(handle, filename) != 0; + lt_dlfree(filename); + if (!error) + return 0; + } + /* try to open the not-installed module */ + if (!installed) { + filename = (char*) + lt_dlmalloc((dir ? strlen(dir) : 0) + + strlen(objdir) + strlen(dlname) + 1); + if (!filename) { + last_error = memory_error; + return 1; + } + if (dir) + strcpy(filename, dir); + else + *filename = 0; + strcat(filename, objdir); + strcat(filename, dlname); + + error = tryall_dlopen(handle, filename) != 0; + lt_dlfree(filename); + if (!error) + return 0; + } + /* maybe it was moved to another directory */ + { + filename = (char*) + lt_dlmalloc((dir ? strlen(dir) : 0) + + strlen(dlname) + 1); + if (dir) + strcpy(filename, dir); + else + *filename = 0; + strcat(filename, dlname); + error = tryall_dlopen(handle, filename) != 0; + lt_dlfree(filename); + if (!error) + return 0; + } + } + last_error = file_not_found_error; + return 1; +} + +static char* +canonicalize_path (path) + const char *path; +{ + char *canonical = NULL; + + if (path && *path) { + char *ptr = strdup (path); + canonical = ptr; +#ifdef LTDL_DIRSEP_CHAR + /* Avoid this overhead where '/' is the only separator. */ + while (ptr = strchr (ptr, LTDL_DIRSEP_CHAR)) + *ptr++ = '/'; +#endif + } + + return canonical; +} + +static lt_ptr_t +find_file (basename, search_path, pdir, handle) + const char *basename; + const char *search_path; + char **pdir; + lt_dlhandle *handle; +{ + /* when handle != NULL search a library, otherwise a file */ + /* return NULL on failure, otherwise the file/handle */ + + lt_ptr_t result = 0; + char *filename = 0; + int filenamesize = 0; + int lenbase = strlen(basename); + char *next = 0; + + if (!search_path || !*search_path) { + last_error = file_not_found_error; + return 0; + } + next = canonicalize_path (search_path); + if (!next) { + last_error = memory_error; + goto cleanup; + } + while (next) { + int lendir; + char *cur = next; + + next = strchr(cur, LTDL_PATHSEP_CHAR); + if (!next) + next = cur + strlen(cur); + lendir = next - cur; + if (*next == LTDL_PATHSEP_CHAR) + ++next; + else + next = 0; + if (lendir == 0) + continue; + if (lendir + 1 + lenbase >= filenamesize) { + if (filename) + lt_dlfree(filename); + filenamesize = lendir + 1 + lenbase + 1; + filename = (char*) lt_dlmalloc(filenamesize); + if (!filename) { + last_error = memory_error; + goto cleanup; + } + } + strncpy(filename, cur, lendir); + if (filename[lendir-1] != '/') + filename[lendir++] = '/'; + strcpy(filename+lendir, basename); + if (handle) { + if (tryall_dlopen(handle, filename) == 0) { + result = (lt_ptr_t) handle; + goto cleanup; + } + } else { + FILE *file = fopen(filename, LTDL_READTEXT_MODE); + if (file) { + if (*pdir) + lt_dlfree(*pdir); + filename[lendir] = '\0'; + *pdir = strdup(filename); + if (!*pdir) { + /* We could have even avoided the + strdup, but there would be some + memory overhead. */ + *pdir = filename; + } else + filename = NULL; + result = (lt_ptr_t) file; + goto cleanup; + } + } + } + last_error = file_not_found_error; +cleanup: + if (filename) + lt_dlfree(filename); + lt_dlfree(next); + return result; +} + +static int +load_deplibs(handle, deplibs) + lt_dlhandle handle; + const char *deplibs; +{ + /* FIXME: load deplibs */ + handle->depcount = 0; + handle->deplibs = 0; + /* Just to silence gcc -Wall */ + deplibs = 0; + return 0; +} + +static int +unload_deplibs(handle) + lt_dlhandle handle; +{ + /* FIXME: unload deplibs */ + /* Just to silence gcc -Wall */ + handle = 0; + return 0; +} + +static inline int +trim (dest, str) + char **dest; + const char *str; +{ + /* remove the leading and trailing "'" from str + and store the result in dest */ + char *tmp; + const char *end = strrchr(str, '\''); + int len = strlen(str); + + if (*dest) + lt_dlfree(*dest); + if (len > 3 && str[0] == '\'') { + tmp = (char*) lt_dlmalloc(end - str); + if (!tmp) { + last_error = memory_error; + return 1; + } + strncpy(tmp, &str[1], (end - str) - 1); + tmp[len-3] = '\0'; + *dest = tmp; + } else + *dest = 0; + return 0; +} + +static inline int +free_vars( dlname, oldname, libdir, deplibs) + char *dlname; + char *oldname; + char *libdir; + char *deplibs; +{ + if (dlname) + lt_dlfree(dlname); + if (oldname) + lt_dlfree(oldname); + if (libdir) + lt_dlfree(libdir); + if (deplibs) + lt_dlfree(deplibs); + return 0; +} + +lt_dlhandle +lt_dlopen (filename) + const char *filename; +{ + lt_dlhandle handle = 0, newhandle; + const char *ext; + const char *saved_error = last_error; + char *canonical = 0, *basename = 0, *dir = 0, *name = 0; + + if (!filename) { + handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t)); + if (!handle) { + last_error = memory_error; + return 0; + } + handle->info.ref_count = 0; + handle->depcount = 0; + handle->deplibs = 0; + newhandle = handle; + if (tryall_dlopen(&newhandle, 0) != 0) { + lt_dlfree(handle); + return 0; + } + goto register_handle; + } + canonical = canonicalize_path (filename); + if (!canonical) { + last_error = memory_error; + if (handle) + lt_dlfree(handle); + return 0; + } + basename = strrchr(canonical, '/'); + if (basename) { + basename++; + dir = (char*) lt_dlmalloc(basename - canonical + 1); + if (!dir) { + last_error = memory_error; + handle = 0; + goto cleanup; + } + strncpy(dir, canonical, basename - canonical); + dir[basename - canonical] = '\0'; + } else + basename = canonical; + /* check whether we open a libtool module (.la extension) */ + ext = strrchr(basename, '.'); + if (ext && strcmp(ext, ".la") == 0) { + /* this seems to be a libtool module */ + FILE *file; + int i; + char *dlname = 0, *old_name = 0; + char *libdir = 0, *deplibs = 0; + char *line; + int error = 0; + /* if we can't find the installed flag, it is probably an + installed libtool archive, produced with an old version + of libtool */ + int installed = 1; + + /* extract the module name from the file name */ + name = (char*) lt_dlmalloc(ext - basename + 1); + if (!name) { + last_error = memory_error; + handle = 0; + goto cleanup; + } + /* canonicalize the module name */ + for (i = 0; i < ext - basename; i++) + if (isalnum((int)(basename[i]))) + name[i] = basename[i]; + else + name[i] = '_'; + name[ext - basename] = '\0'; + /* now try to open the .la file */ + file = fopen(filename, LTDL_READTEXT_MODE); + if (!file) + last_error = file_not_found_error; + if (!file && !dir) { + /* try other directories */ + file = (FILE*) find_file(basename, + user_search_path, + &dir, 0); + if (!file) + file = (FILE*) find_file(basename, + getenv("LTDL_LIBRARY_PATH"), + &dir, 0); +#ifdef LTDL_SHLIBPATH_VAR + if (!file) + file = (FILE*) find_file(basename, + getenv(LTDL_SHLIBPATH_VAR), + &dir, 0); +#endif + } + if (!file) { + handle = 0; + goto cleanup; + } + line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX); + if (!line) { + fclose(file); + last_error = memory_error; + handle = 0; + goto cleanup; + } + /* read the .la file */ + while (!feof(file)) { + if (!fgets(line, LTDL_FILENAME_MAX, file)) + break; + if (line[0] == '\n' || line[0] == '#') + continue; +# undef STR_DLNAME +# define STR_DLNAME "dlname=" + if (strncmp(line, STR_DLNAME, + sizeof(STR_DLNAME) - 1) == 0) + error = trim(&dlname, + &line[sizeof(STR_DLNAME) - 1]); + else +# undef STR_OLD_LIBRARY +# define STR_OLD_LIBRARY "old_library=" + if (strncmp(line, STR_OLD_LIBRARY, + sizeof(STR_OLD_LIBRARY) - 1) == 0) + error = trim(&old_name, + &line[sizeof(STR_OLD_LIBRARY) - 1]); + else +# undef STR_LIBDIR +# define STR_LIBDIR "libdir=" + if (strncmp(line, STR_LIBDIR, + sizeof(STR_LIBDIR) - 1) == 0) + error = trim(&libdir, + &line[sizeof(STR_LIBDIR) - 1]); + else +# undef STR_DL_DEPLIBS +# define STR_DL_DEPLIBS "dl_dependency_libs=" + if (strncmp(line, STR_DL_DEPLIBS, + sizeof(STR_DL_DEPLIBS) - 1) == 0) + error = trim(&deplibs, + &line[sizeof(STR_DL_DEPLIBS) - 1]); + else + if (strcmp(line, "installed=yes\n") == 0) + installed = 1; + else + if (strcmp(line, "installed=no\n") == 0) + installed = 0; + if (error) + break; + } + fclose(file); + lt_dlfree(line); + /* allocate the handle */ + handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t)); + if (!handle || error) { + if (handle) + lt_dlfree(handle); + if (!error) + last_error = memory_error; + free_vars(dlname, old_name, libdir, deplibs); + /* handle is already set to 0 */ + goto cleanup; + } + handle->info.ref_count = 0; + if (load_deplibs(handle, deplibs) == 0) { + newhandle = handle; + /* find_module may replace newhandle */ + if (find_module(&newhandle, dir, libdir, + dlname, old_name, installed)) { + unload_deplibs(handle); + error = 1; + } + } else + error = 1; + free_vars(dlname, old_name, libdir, deplibs); + if (error) { + lt_dlfree(handle); + handle = 0; + goto cleanup; + } + if (handle != newhandle) + unload_deplibs(handle); + } else { + /* not a libtool module */ + handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t)); + if (!handle) { + last_error = memory_error; + /* handle is already set to 0 */ + goto cleanup; + } + handle->info.ref_count = 0; + /* non-libtool modules don't have dependencies */ + handle->depcount = 0; + handle->deplibs = 0; + newhandle = handle; + if (tryall_dlopen(&newhandle, filename) + && (dir + || (!find_file(basename, user_search_path, + 0, &newhandle) + && !find_file(basename, + getenv("LTDL_LIBRARY_PATH"), + 0, &newhandle) +#ifdef LTDL_SHLIBPATH_VAR + && !find_file(basename, + getenv(LTDL_SHLIBPATH_VAR), + 0, &newhandle) +#endif + ))) { + lt_dlfree(handle); + handle = 0; + goto cleanup; + } + } +register_handle: + if (newhandle != handle) { + lt_dlfree(handle); + handle = newhandle; + } + if (!handle->info.ref_count) { + handle->info.ref_count = 1; + handle->app_private = 0; + handle->info.name = name; + handle->next = handles; + handles = handle; + name = 0; /* don't free this during `cleanup' */ + } + last_error = saved_error; +cleanup: + if (dir) + lt_dlfree(dir); + if (name) + lt_dlfree(name); + if (canonical) + lt_dlfree(canonical); + return handle; +} + +lt_dlhandle +lt_dlopenext (filename) + const char *filename; +{ + lt_dlhandle handle; + char *tmp; + int len; + const char *saved_error = last_error; + + if (!filename) + return lt_dlopen(filename); + len = strlen(filename); + if (!len) { + last_error = file_not_found_error; + return 0; + } + /* try the normal file name */ + handle = lt_dlopen(filename); + if (handle) + return handle; + /* try "filename.la" */ + tmp = (char*) lt_dlmalloc(len+4); + if (!tmp) { + last_error = memory_error; + return 0; + } + strcpy(tmp, filename); + strcat(tmp, ".la"); + handle = lt_dlopen(tmp); + if (handle) { + last_error = saved_error; + lt_dlfree(tmp); + return handle; + } +#ifdef LTDL_SHLIB_EXT + /* try "filename.EXT" */ + if (strlen(shlib_ext) > 3) { + lt_dlfree(tmp); + tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1); + if (!tmp) { + last_error = memory_error; + return 0; + } + strcpy(tmp, filename); + } else + tmp[len] = '\0'; + strcat(tmp, shlib_ext); + handle = lt_dlopen(tmp); + if (handle) { + last_error = saved_error; + lt_dlfree(tmp); + return handle; + } +#endif + last_error = file_not_found_error; + lt_dlfree(tmp); + return 0; +} + +int +lt_dlclose (handle) + lt_dlhandle handle; +{ + lt_dlhandle cur, last; + + /* check whether the handle is valid */ + last = cur = handles; + while (cur && handle != cur) { + last = cur; + cur = cur->next; + } + if (!cur) { + last_error = invalid_handle_error; + return 1; + } + handle->info.ref_count--; + if (!handle->info.ref_count) { + int error; + + if (handle != handles) + last->next = handle->next; + else + handles = handle->next; + error = handle->type->lib_close(handle); + error += unload_deplibs(handle); + if (handle->info.filename) + lt_dlfree(handle->info.filename); + if (handle->info.name) + lt_dlfree(handle->info.name); + lt_dlfree(handle); + return error; + } + return 0; +} + +lt_ptr_t +lt_dlsym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + int lensym; + char lsym[LTDL_SYMBOL_LENGTH]; + char *sym; + lt_ptr_t address; + + if (!handle) { + last_error = invalid_handle_error; + return 0; + } + if (!symbol) { + last_error = symbol_error; + return 0; + } + lensym = strlen(symbol); + if (handle->type->sym_prefix) + lensym += strlen(handle->type->sym_prefix); + if (handle->info.name) + lensym += strlen(handle->info.name); + if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH) + sym = lsym; + else + sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1); + if (!sym) { + last_error = buffer_overflow_error; + return 0; + } + if (handle->info.name) { + const char *saved_error = last_error; + + /* this is a libtool module */ + if (handle->type->sym_prefix) { + strcpy(sym, handle->type->sym_prefix); + strcat(sym, handle->info.name); + } else + strcpy(sym, handle->info.name); + strcat(sym, "_LTX_"); + strcat(sym, symbol); + /* try "modulename_LTX_symbol" */ + address = handle->type->find_sym(handle, sym); + if (address) { + if (sym != lsym) + lt_dlfree(sym); + return address; + } + last_error = saved_error; + } + /* otherwise try "symbol" */ + if (handle->type->sym_prefix) { + strcpy(sym, handle->type->sym_prefix); + strcat(sym, symbol); + } else + strcpy(sym, symbol); + address = handle->type->find_sym(handle, sym); + if (sym != lsym) + lt_dlfree(sym); + return address; +} + +const char * +lt_dlerror LTDL_PARAMS((void)) +{ + const char *error = last_error; + + last_error = 0; + return error; +} + +int +lt_dladdsearchdir (search_dir) + const char *search_dir; +{ + if (!search_dir || !strlen(search_dir)) + return 0; + if (!user_search_path) { + user_search_path = strdup(search_dir); + if (!user_search_path) { + last_error = memory_error; + return 1; + } + } else { + char *new_search_path = (char*) + lt_dlmalloc(strlen(user_search_path) + + strlen(search_dir) + 2); /* ':' + '\0' == 2 */ + if (!new_search_path) { + last_error = memory_error; + return 1; + } + sprintf (new_search_path, "%s%c%s", user_search_path, + LTDL_PATHSEP_CHAR, search_dir); + lt_dlfree(user_search_path); + user_search_path = new_search_path; + } + return 0; +} + +int +lt_dlsetsearchpath (search_path) + const char *search_path; +{ + if (user_search_path) + lt_dlfree(user_search_path); + user_search_path = 0; /* reset the search path */ + if (!search_path || !strlen(search_path)) + return 0; + user_search_path = strdup(search_path); + if (!user_search_path) + return 1; + return 0; +} + +const char * +lt_dlgetsearchpath LTDL_PARAMS((void)) +{ + return user_search_path; +} + +int +lt_dlsetdata (handle, data) + lt_dlhandle handle; + lt_ptr_t data; +{ + if (!handle) { + last_error = invalid_handle_error; + return 1; + } + handle->app_private = data; + return 0; +} + +lt_ptr_t +lt_dlgetdata (handle) + lt_dlhandle handle; +{ + if (!handle) { + last_error = invalid_handle_error; + return 0; + } + return handle->app_private; +} + +const lt_dlinfo * +lt_dlgetinfo (handle) + lt_dlhandle handle; +{ + if (!handle) { + last_error = invalid_handle_error; + return 0; + } + return &(handle->info); +} diff --git a/src/ltdl.h b/src/ltdl.h new file mode 100644 index 00000000..0fafa207 --- /dev/null +++ b/src/ltdl.h @@ -0,0 +1,141 @@ +/* ltdl.h -- generic dlopen functions + Copyright (C) 1998-2000 Free Software Foundation, Inc. + Originally by Thomas Tanner <tanner@ffii.org> + This file is part of GNU Libtool. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Library General Public License, +if you distribute this file as part of a program that uses GNU libtool +to create libraries and programs, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA +*/ + +/* Only include this header file once. */ +#ifndef _LTDL_H_ +#define _LTDL_H_ 1 + +/* Canonicalise Windows and Cygwin recognition macros. */ +#ifdef __CYGWIN32__ +# ifndef __CYGWIN__ +# define __CYGWIN__ __CYGWIN32__ +# endif +#endif +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 _WIN32 +# endif +#endif + +/* __BEGIN_DECLS should be used at the beginning of your declarations, + so that C++ compilers don't mangle their names. Use __END_DECLS at + the end of C declarations. */ +#undef __BEGIN_DECLS +#undef __END_DECLS +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS /* empty */ +# define __END_DECLS /* empty */ +#endif + +/* LTDL_PARAMS is a macro used to wrap function prototypes, so that compilers + that don't understand ANSI C prototypes still work, and ANSI C + compilers can issue warnings about type mismatches. */ +#undef LTDL_PARAMS +#undef lt_ptr_t +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) +# define LTDL_PARAMS(protos) protos +# define lt_ptr_t void* +#else +# define LTDL_PARAMS(protos) () +# define lt_ptr_t char* +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ +/* LTDL_DIRSEP_CHAR is accepted *in addition* to '/' as a directory + separator when it is set. */ +# define LTDL_DIRSEP_CHAR '\\' +# define LTDL_PATHSEP_CHAR ';' +# endif +#endif +#ifndef LTDL_PATHSEP_CHAR +# define LTDL_PATHSEP_CHAR ':' +#endif + +/* DLL building support on win32 hosts; mostly to workaround their + ridiculous implementation of data symbol exporting. */ +#ifndef LTDL_SCOPE +# ifdef _WIN32 +# ifdef DLL_EXPORT /* defined by libtool (if required) */ +# define LTDL_SCOPE __declspec(dllexport) +# endif +# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ +# define LTDL_SCOPE extern __declspec(dllimport) +# endif +# endif +# ifndef LTDL_SCOPE /* static linking or !_WIN32 */ +# define LTDL_SCOPE extern +# endif +#endif + +#include <stdlib.h> + +#ifdef _LTDL_COMPILE_ +typedef struct lt_dlhandle_t *lt_dlhandle; +#else +typedef lt_ptr_t lt_dlhandle; +#endif + +typedef struct { + const char *name; + lt_ptr_t address; +} lt_dlsymlist; + +typedef struct { + char *filename; /* file name */ + char *name; /* module name */ + int ref_count; /* reference count */ +} lt_dlinfo; + +__BEGIN_DECLS +extern int lt_dlinit LTDL_PARAMS((void)); +extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded)); +extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded)); +extern int lt_dlexit LTDL_PARAMS((void)); +extern lt_dlhandle lt_dlopen LTDL_PARAMS((const char *filename)); +extern lt_dlhandle lt_dlopenext LTDL_PARAMS((const char *filename)); +extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle)); +extern lt_ptr_t lt_dlsym LTDL_PARAMS((lt_dlhandle handle, const char *name)); +extern const char *lt_dlerror LTDL_PARAMS((void)); +extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir)); +extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path)); +extern const char *lt_dlgetsearchpath LTDL_PARAMS((void)); +extern int lt_dlsetdata LTDL_PARAMS((lt_dlhandle handle, lt_ptr_t data)); +extern lt_ptr_t lt_dlgetdata LTDL_PARAMS((lt_dlhandle handle)); +extern const lt_dlinfo *lt_dlgetinfo LTDL_PARAMS((lt_dlhandle handle)); + +LTDL_SCOPE const lt_dlsymlist lt_preloaded_symbols[]; +#define LTDL_SET_PRELOADED_SYMBOLS() lt_dlpreload_default(lt_preloaded_symbols) + +LTDL_SCOPE lt_ptr_t (*lt_dlmalloc)LTDL_PARAMS((size_t size)); +LTDL_SCOPE void (*lt_dlfree)LTDL_PARAMS((lt_ptr_t ptr)); + +__END_DECLS + +#endif /* !_LTDL_H_ */ diff --git a/src/m4.c b/src/m4.c new file mode 100644 index 00000000..cdb1b74c --- /dev/null +++ b/src/m4.c @@ -0,0 +1,493 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "m4.h" + +#include <getopt.h> +#include <sys/signal.h> + +static void usage _((int)); + +/* Operate interactively (-e). */ +static int interactive = 0; + +/* 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). */ +int 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 = 250; + +#ifdef ENABLE_CHANGEWORD +/* User provided regexp for describing m4 words. */ +const char *user_word_regexp = NULL; +#endif + +/* Name of frozen file to digest after initialization. */ +const char *frozen_file_to_read = NULL; + +/* Name of frozen file to produce near completion. */ +const char *frozen_file_to_write = NULL; + +/* The name this program was run with. */ +const char *program_name; + +/* If non-zero, display usage information and exit. */ +static int show_help = 0; + +/* If non-zero, print the version on standard output and exit. */ +static int show_version = 0; + +struct macro_definition +{ + struct macro_definition *next; + int code; /* D, U or t */ + const char *macro; +}; +typedef struct macro_definition macro_definition; + +/* Error handling functions. */ + +/*-------------------------------------------------------------------------. +| Print source and line reference on standard error, as a prefix for error | +| messages. Flush standard output first. | +`-------------------------------------------------------------------------*/ + +void +reference_error (void) +{ + fflush (stdout); + fprintf (stderr, "%s:%d: ", current_file, current_line); +} + +#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 */ + +/* Memory allocation. */ + +/*------------------------. +| Failsafe free routine. | +`------------------------*/ + +void +xfree (voidstar p) +{ + if (p != NULL) + free (p); +} + + +/*---------------------------------------------. +| 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 ("\ +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, --interactive unbuffer output, ignore interrupts\n\ + -E, --fatal-warnings stop execution after first warning\n\ + -Q, --quiet, --silent suppress some warnings for builtins\n\ + -P, --prefix-builtins force a `m4_' prefix to all 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\ + -I, --include=DIRECTORY search this directory second for includes\n\ + -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n\ + -U, --undefine=NAME delete builtin NAME\n\ + -s, --synclines generate `#line NO \"FILE\"' lines\n", + stdout); + fputs ("\ +\n\ +Limits control:\n\ + -G, --traditional suppress all GNU extensions\n\ + -H, --hashsize=PRIME set symbol lookup hash table size\n\ + -L, --nesting-limit=NUMBER change artificial nesting limit\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\ + -t, --trace=NAME trace NAME when it will be defined\n\ + -l, --arglength=NUM restrict macro tracing size\n\ + -o, --error-output=FILE redirect debug and trace output\n", + stdout); + fputs ("\ +\n\ +FLAGS is any of:\n\ + t trace for all macro calls, not only traceon'ed\n\ + a show actual arguments\n\ + e show expansion\n\ + q quote values as necessary, with a or e flag\n\ + c show before collect, after collect and after call\n\ + x add a unique macro call id, useful with c flag\n\ + f say current input file name\n\ + l say current input line number\n\ + p show results of path searches\n\ + i show changes in input files\n\ + V shorthand for all of the above flags\n", + stdout); + fputs ("\ +\n\ +If no FILE or if FILE is `-', standard input is read.\n", + stdout); + } + exit (status); +} + +/*--------------------------------------. +| Decode options and launch execution. | +`--------------------------------------*/ + +static const struct option long_options[] = +{ + {"arglength", required_argument, NULL, 'l'}, + {"debug", optional_argument, NULL, 'd'}, + {"diversions", required_argument, NULL, 'N'}, + {"error-output", required_argument, NULL, 'o'}, + {"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, 'e'}, + {"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'}, + {"traditional", no_argument, NULL, 'G'}, + {"word-regexp", required_argument, NULL, 'W'}, + + {"help", no_argument, &show_help, 1}, + {"version", no_argument, &show_version, 1}, + + /* These are somewhat troublesome. */ + { "define", required_argument, NULL, 'D' }, + { "undefine", required_argument, NULL, 'U' }, + { "trace", required_argument, NULL, 't' }, + + { 0, 0, 0, 0 }, +}; + +#ifdef ENABLE_CHANGEWORD +#define OPTSTRING "B:D:EF:GH:I:L:N:PQR:S:T:U:W:d::el:o:st:" +#else +#define OPTSTRING "B:D:EF:GH:I:L:N:PQR:S:T:U:d::el: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 *new; + int optchar; /* option character */ + + macro_definition *defines; + FILE *fp; + + program_name = argv[0]; + + 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, argv, OPTSTRING, long_options, NULL), + optchar != EOF) + switch (optchar) + { + default: + usage (EXIT_FAILURE); + + case 0: + break; + + case 'B': /* compatibility junk */ + case 'N': + case 'S': + case 'T': + break; + + case 'D': + case 'U': + case 't': + + /* Arguments that cannot be handled until later are accumulated. */ + + new = (macro_definition *) xmalloc (sizeof (macro_definition)); + new->code = optchar; + new->macro = optarg; + new->next = NULL; + + if (head == NULL) + head = new; + else + tail->next = new; + tail = new; + + 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 = atoi (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': + interactive = 1; + break; + + case 'l': + max_debug_argument_length = atoi (optarg); + if (max_debug_argument_length <= 0) + max_debug_argument_length = 0; + break; + + case 'o': + if (!debug_set_output (optarg)) + error (0, errno, optarg); + break; + + case 's': + sync_output = 1; + break; + } + + if (show_version) + { + printf ("GNU %s %s\n", PRODUCT, VERSION); + exit (EXIT_SUCCESS); + } + + if (show_help) + usage (EXIT_SUCCESS); + + defines = head; + + /* Do the basic initialisations. */ + + input_init (); + output_init (); + symtab_init (); + include_env_init (); + + if (frozen_file_to_read) + reload_frozen_state (frozen_file_to_read); + else + builtin_init (); + + /* Handle deferred command line macro definitions. Must come after + initialisation of the symbol table. */ + + while (defines != NULL) + { + macro_definition *next; + char *macro_value; + symbol *sym; + + switch (defines->code) + { + case 'D': + macro_value = strchr (defines->macro, '='); + if (macro_value == NULL) + macro_value = ""; + else + *macro_value++ = '\0'; + define_user_macro (defines->macro, macro_value, SYMBOL_INSERT); + break; + + case 'U': + lookup_symbol (defines->macro, SYMBOL_DELETE); + break; + + case 't': + sym = lookup_symbol (defines->macro, SYMBOL_INSERT); + SYMBOL_TRACED (sym) = TRUE; + break; + + default: + M4ERROR ((warning_status, 0, + "INTERNAL ERROR: Bad code in deferred arguments")); + abort (); + } + + next = defines->next; + xfree ((voidstar) defines); + defines = next; + } + + /* Interactive mode means unbuffered output, and interrupts ignored. */ + + if (interactive) + { + signal (SIGINT, SIG_IGN); + setbuf (stdout, (char *) NULL); + } + + /* Handle the various input files. Each file is pushed on the input, + and the input read. Wrapup text is handled separately later. */ + + if (optind == argc) + { + push_file (stdin, "stdin"); + expand_input (); + } + else + for (; optind < argc; optind++) + { + if (strcmp (argv[optind], "-") == 0) + push_file (stdin, "stdin"); + else + { + fp = path_search (argv[optind]); + if (fp == NULL) + { + error (0, errno, argv[optind]); + continue; + } + else + push_file (fp, argv[optind]); + } + expand_input (); + } +#undef NEXTARG + + /* Now handle wrapup text. */ + + while (pop_wrapup ()) + expand_input (); + + if (frozen_file_to_write) + produce_frozen_state (frozen_file_to_write); + else + { + make_diversion (0); + undivert_all (); + } + + exit (EXIT_SUCCESS); +} diff --git a/src/m4.h b/src/m4.h new file mode 100644 index 00000000..feb37573 --- /dev/null +++ b/src/m4.h @@ -0,0 +1,475 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* We use <config.h> 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). */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#if __STDC__ +# define voidstar void * +#else +# define voidstar char * +#endif + +#ifdef PROTOTYPES +# define _(Args) Args +#else +# define _(Args) () +#endif + +#include <stdio.h> +#include <ctype.h> + +#include "obstack.h" + +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ + +#if defined (HAVE_STRING_H) || defined (STDC_HEADERS) +# include <string.h> +# if !defined (STDC_HEADERS) && defined (HAVE_MEMORY_H) +# include <memory.h> +# endif +/* This is for obstack code -- should live in obstack.h. */ +# ifndef bcopy +# define bcopy(S, D, N) memcpy ((D), (S), (N)) +# endif +#else +# include <strings.h> +# ifndef memcpy +# define memcpy(D, S, N) bcopy((S), (D), (N)) +# endif +# ifndef strchr +# define strchr(S, C) index ((S), (C)) +# endif +# ifndef strrchr +# define strrchr(S, C) rindex ((S), (C)) +# endif +# ifndef bcopy +void bcopy (); +# endif +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +#else /* not STDC_HEADERS */ + +voidstar malloc (); +voidstar realloc (); +char *getenv (); +double atof (); +long strtol (); + +#endif /* STDC_HEADERS */ + +/* Some systems do not define EXIT_*, even with STDC_HEADERS. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +/* If FALSE is defined, we presume TRUE is defined too. In this case, + merely typedef boolean as being int. Or else, define these all. */ +#ifndef FALSE +/* Do not use `enum boolean': this tag is used in SVR4 <sys/types.h>. */ +typedef enum { FALSE = 0, TRUE = 1 } boolean; +#else +typedef int boolean; +#endif + +char *mktemp (); + +/* Various declarations. */ + +struct string + { + char *string; /* characters of the string */ + size_t length; /* length of the string */ + }; +typedef struct string STRING; + +/* Memory allocation. */ +voidstar xmalloc _((unsigned int)); +voidstar xrealloc _((voidstar , unsigned int)); +void xfree _((voidstar)); +char *xstrdup _((const char *)); +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free xfree + +/* Other library routines. */ +void error _((int, int, const char *, ...)); + +/* Those must come first. */ +typedef void builtin_func (); +typedef struct token_data token_data; + +/* File: m4.c --- global definitions. */ + +/* Option flags. */ +extern int sync_output; /* -s */ +extern int debug_level; /* -d */ +extern int 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. */ +#define M4ERROR(Arglist) \ + (reference_error (), error Arglist) + +void reference_error _((void)); + +#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)); +boolean 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 */ + TOKEN_WORD, /* an identifier */ + TOKEN_SIMPLE, /* a single character */ + TOKEN_MACDEF /* a macros 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; + struct + { + builtin_func *func; + boolean traced; + } + u_f; + } + 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.u_f.func) +#define TOKEN_DATA_FUNC_TRACED(Td) ((Td)->u.u_f.traced) + +typedef enum token_type token_type; +typedef enum token_data_type token_data_type; + +void input_init _((void)); +int peek_input _((void)); +token_type next_token _((token_data *)); +void skip_line _((void)); + +/* push back input */ +void push_file _((FILE *, const char *)); +void push_macro _((builtin_func *, boolean)); +struct obstack *push_string_init _((void)); +const char *push_string_finish _((void)); +void push_wrapup _((const char *)); +boolean 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 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; + boolean traced; + boolean shadowed; + boolean macro_args; + boolean blind_no_args; + + 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_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 (); + +#define HASHMAX 509 /* default, overridden by -Hsize */ + +extern symbol **symtab; + +void symtab_init _((void)); +symbol *lookup_symbol _((const char *, symbol_lookup)); +void hack_all_symbols _((hack_symbol *, const char *)); + +/* 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; + boolean gnu_extension; + boolean groks_macro_args; + boolean blind_if_no_args; + 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, boolean)); +void define_user_macro _((const char *, const char *, symbol_lookup)); +void undivert_all _((void)); +void expand_user_macro _((struct obstack *, symbol *, 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 *path_search _((const 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; + +boolean 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 <dmalloc.h> +#endif + +/* Other debug stuff. */ + +#ifdef DEBUG +# define DEBUG_INPUT +# define DEBUG_MACRO +# define DEBUG_SYM +# define DEBUG_INCL +#endif diff --git a/src/macro.c b/src/macro.c new file mode 100644 index 00000000..16cfa6cf --- /dev/null +++ b/src/macro.c @@ -0,0 +1,316 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, 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; + +/*----------------------------------------------------------------------. +| This function read all input, and expands each token, one at a time. | +`----------------------------------------------------------------------*/ + +void +expand_input (void) +{ + token_type t; + token_data td; + + while ((t = next_token (&td)) != TOKEN_EOF) + expand_token ((struct obstack *) NULL, t, &td); +} + + +/*------------------------------------------------------------------------. +| 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_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_input () != '(')) + { +#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 boolean +expand_argument (struct obstack *obs, token_data *argp) +{ + token_type t; + token_data td; + char *text; + int paren_level; + + TOKEN_DATA_TYPE (argp) = TOKEN_VOID; + + /* Skip leading white space. */ + do + { + t = next_token (&td); + } + while (t == TOKEN_SIMPLE && isspace (*TOKEN_DATA_TEXT (&td))); + + paren_level = 0; + + while (1) + { + + switch (t) + { /* TOKSW */ + case TOKEN_SIMPLE: + text = TOKEN_DATA_TEXT (&td); + if ((*text == ',' || *text == ')') && paren_level == 0) + { + + /* The argument MUST be finished, whether we want it or not. */ + obstack_1grow (obs, '\0'); + text = obstack_finish (obs); + + if (TOKEN_DATA_TYPE (argp) == TOKEN_VOID) + { + TOKEN_DATA_TYPE (argp) = TOKEN_TEXT; + TOKEN_DATA_TEXT (argp) = text; + } + return (boolean) (*TOKEN_DATA_TEXT (&td) == ','); + } + + if (*text == '(') + paren_level++; + else if (*text == ')') + paren_level--; + expand_token (obs, t, &td); + break; + + case TOKEN_EOF: + M4ERROR ((EXIT_FAILURE, 0, + "ERROR: EOF 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); + TOKEN_DATA_FUNC_TRACED (argp) = TOKEN_DATA_FUNC_TRACED (&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) +{ + int ch; /* lookahead for ( */ + token_data td; + token_data *tdp; + boolean more_args; + boolean 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, (voidstar) &td, sizeof (td)); + obstack_grow (argptr, (voidstar) &tdp, sizeof (tdp)); + + ch = peek_input (); + if (ch == '(') + { + 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) = ""; + } + tdp = (token_data *) + obstack_copy (arguments, (voidstar) &td, sizeof (td)); + obstack_grow (argptr, (voidstar) &tdp, sizeof (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; + struct obstack argptr; + token_data **argv; + int argc; + struct obstack *expansion; + const char *expanded; + boolean traced; + int my_call_id; + + expansion_level++; + if (expansion_level > nesting_limit) + M4ERROR ((EXIT_FAILURE, 0, + "ERROR: Recursion limit of %d exceeded, use -L<N> to change it", + nesting_limit)); + + macro_call_id++; + my_call_id = macro_call_id; + + traced = (boolean) ((debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym)); + + obstack_init (&argptr); + obstack_init (&arguments); + + if (traced && (debug_level & DEBUG_TRACE_CALL)) + trace_prepre (SYMBOL_NAME (sym), my_call_id); + + collect_arguments (sym, &argptr, &arguments); + + argc = obstack_object_size (&argptr) / sizeof (token_data *); + argv = (token_data **) obstack_finish (&argptr); + + 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); + + --expansion_level; + + obstack_free (&arguments, NULL); + obstack_free (&argptr, NULL); +} diff --git a/src/module.c b/src/module.c new file mode 100644 index 00000000..fb42884c --- /dev/null +++ b/src/module.c @@ -0,0 +1,206 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "m4.h" + +#ifdef WITH_MODULES + +#define DEBUG_MODULES +#undef DEBUG_MODULES + +/* + * This file implements dynamic modules in GNU m4. A module is a + * compiled shared object, that can be linked into GNU m4 at run + * time. Information about creating modules is in ../modules/README. + * + * The current implementation uses dlopen(3). To enable this + * experimental feature give configure the `--with-modules' switch. + * This implementation is only tested on Linux. + * + * A m4 module need only define one external symbol, called + * `m4_macro_table'. This symbol should point to a table of `struct + * builtin' exactly as the one in builtin.c. This table is pushed on a + * list of builtin tables and each definition therein is added to the + * symbol table. + * + * The code implementing loadable modules is modest. It is divided + * between the files path.c (search in module path), builtin.c (user + * interface and support for multiple builtin tables) and this file (OS + * dependant routines). + * + * To load a module, use `loadmodule(modulename.so)', where .so is the + * normal extention for shared object files. The function + * `m4_loadmodule' calls module_load() in this file, which uses + * module_search() in path.c to find the module in the module search + * path. This path is initialised from the environment variable + * M4MODPATH, and cannot be modified in any way. Module_search() + * constructs absolute file names and calls module_try_load() in this + * file. This function returns NULL on failure and a non-NULL void* on + * success. If succesful module_search() returns the value of this + * void*, which is a handle for the vm segment mapped. Module_load() + * checks to see if the module is alreay loaded, and if not, retrives + * the symbol `m4_macro_table' and returns it's value to + * m4_loadmodule(). This pointer should be a builtin*, which is + * installed using install_builtin_table(). + * + * When a module is loaded, the function "void m4_init_module(struct + * obstack *obs)" is called, if defined. Any non NULL return value of + * this function will be the expansion of "loadmodule". Before program + * exit, all modules are unloaded and the function "void + * m4_finish_module(void)" is called, if defined. + * + * There is no way to unload a module unless at program exit. It is + * safe to load the same module several times, it has no effect. + **/ + +#include <dlfcn.h> + +/* This list is used to check for repeated loading of the same modules. */ + +struct module_list { + struct module_list *next; + char *modname; + void *handle; +}; + +typedef struct module_list module_list; + +static module_list *modules; + +/* + * Initialisation. Currently the module search path in path.c is + * initialised from M4MODPATH. Only absolute path names are accepted to + * prevent the path search of the dlopen library from finding wrong + * files. + */ +void +module_init (void) +{ + module_env_init (); +} + +/* + * Attempt to load a module with a absolute file name. It is used as a + * callback from module_search() in path.c. + */ +voidstar +module_try_load (const char *modname) +{ + return dlopen (modname, RTLD_NOW); +} + + +/* + * Load a module. Modname can be a absolute file name or, if relative, + * is is searched in the module path. Return value is the value of the + * symbol `m4_macro_table' in the module. The module is unloaded in + * case of error. The builtins from the module are installed in the + * symbol table by the caller, m4_loadmodule() in builtin.c. + */ + +struct builtin * +module_load (const char *modname, struct obstack *obs) +{ + void *handle; + struct module_list *list; + + builtin *btab; + module_init_t *init_func; + + handle = module_search(modname, module_try_load); + if (handle == NULL) + { + M4ERROR ((1, 0, _("Error: cannot find module `%s'"), modname)); + } + + for (list = modules; list != NULL; list = list->next) + if (list->handle == handle) + { +#ifdef DEBUG_MODULES + DEBUG_MESSAGE1("module %s handle already seen", modname); +#endif /* DEBUG_MODULES */ + dlclose(handle); + return NULL; + } + + btab = (builtin *) dlsym (handle, "m4_macro_table"); + if (btab == NULL) { +#ifdef DEBUG_MODULES + DEBUG_MESSAGE1("module %s no symbol m4_macro_table", modname); +#endif /* DEBUG_MODULES */ + dlclose(handle); + return NULL; + } + + list = xmalloc (sizeof (struct module_list)); + list->next = modules; + list->modname = xstrdup(modname); + list->handle = handle; + modules = list; + +#ifdef DEBUG_MODULES + DEBUG_MESSAGE1("module %s loaded ok", modname); +#endif /* DEBUG_MODULES */ + + init_func = (module_init_t *) dlsym (handle, "m4_init_module"); + if (init_func != NULL) + { + (*init_func)(obs); + +#ifdef DEBUG_MODULES + DEBUG_MESSAGE1("module %s init hook called", modname); +#endif /* DEBUG_MODULES */ + } + + return btab; +} + +void +module_unload_all(void) +{ + struct module_list *next; + module_finish_t *finish_func; + + while (modules != NULL) + { + finish_func = (module_finish_t *) dlsym (modules->handle, + "m4_finish_module"); + if (finish_func != NULL) + { + (*finish_func)(); + +#ifdef DEBUG_MODULES + DEBUG_MESSAGE1("module %s finish hook called", modules->modname); +#endif /* DEBUG_MODULES */ + } + + dlclose(modules->handle); + +#ifdef DEBUG_MODULES + DEBUG_MESSAGE1("module %s unloaded", modules->modname); +#endif /* DEBUG_MODULES */ + + next = modules->next; + xfree(modules); + modules = next; + } +} + + + +#endif /* WITH_MODULES */ diff --git a/src/numb.c b/src/numb.c new file mode 100644 index 00000000..8dfa077e --- /dev/null +++ b/src/numb.c @@ -0,0 +1,418 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1995, 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file contains the functions to evaluate integer or multiple + precision expressions for the "eval" macro. + */ + +#include "m4.h" +#include "numb.h" + + +#ifdef WITH_GMP + +eval_t numb_ZERO; +eval_t numb_ONE; + +static int numb_initialised = 0; + +void +numb_initialise(void) { + if (numb_initialised) + return; + + numb_init(numb_ZERO); + numb_set_si(&numb_ZERO,0); + + numb_init(numb_ONE); + numb_set_si(&numb_ONE,1); + + numb_initialised = 1; +} + +void +numb_obstack(struct obstack *obs, const eval_t value, + const int radix, int min) +{ + const char *s; + + mpz_t i; + mpz_init(i); + + mpq_get_num(i,value); + s = mpz_get_str((char *)0, radix, i); + + if (*s == '-') + { + obstack_1grow (obs, '-'); + min--; + s++; + } + for (min -= strlen (s); --min >= 0;) + obstack_1grow (obs, '0'); + + obstack_grow (obs, s, strlen (s)); + + mpq_get_den(i,value); + if (mpz_cmp_si(i,(long)1)!=0) { + obstack_1grow (obs, ':'); + s = mpz_get_str((char *)0, radix, i); + obstack_grow (obs, s, strlen (s)); + } + + mpz_clear(i); +} + +#define NOISY "" +#define QUIET (char *)0 + +static void +mpq2mpz(mpz_t z, const eval_t q, const char *noisily) +{ + if (noisily && mpz_cmp_si(mpq_denref(q),(long)1)!=0) { + M4ERROR((warning_status, 0, + _("Loss of precision in eval: %s"), + noisily)); + } + mpz_div(z,mpq_numref(q),mpq_denref(q)); +} + +static void +mpz2mpq(eval_t q, const mpz_t z) +{ + mpq_set_si(q,(long)0,(unsigned long)1); + mpq_set_num(q,z); +} + +void +numb_divide(eval_t *x, const eval_t *y) +{ + mpq_t qres; + mpz_t zres; + + mpq_init(qres); + mpq_div(qres,*x,*y); + + mpz_init(zres); + mpz_div(zres,mpq_numref(qres),mpq_denref(qres)); + mpq_clear(qres); + + mpz2mpq(*x,zres); + mpz_clear(zres); +} + +void +numb_modulo(eval_t *x, const eval_t *y) +{ + mpz_t xx, yy, res; + + /* x should be integral */ + /* y should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(yy); + mpq2mpz(yy,*y,NOISY); + + mpz_init(res); + mpz_mod(res,xx,yy); + + mpz_clear(xx); + mpz_clear(yy); + + mpz2mpq(*x,res); + mpz_clear(res); +} + +void +numb_and(eval_t *x, const eval_t *y) +{ + mpz_t xx, yy, res; + + /* x should be integral */ + /* y should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(yy); + mpq2mpz(yy,*y,NOISY); + + mpz_init(res); + mpz_and(res,xx,yy); + + mpz_clear(xx); + mpz_clear(yy); + + mpz2mpq(*x,res); + mpz_clear(res); +} + +void +numb_ior(eval_t *x, const eval_t *y) +{ + mpz_t xx, yy, res; + + /* x should be integral */ + /* y should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(yy); + mpq2mpz(yy,*y,NOISY); + + mpz_init(res); + mpz_ior(res,xx,yy); + + mpz_clear(xx); + mpz_clear(yy); + + mpz2mpq(*x,res); + mpz_clear(res); +} + +void +numb_eor(eval_t *x, const eval_t *y) +{ + mpz_t xx, yy, res; + + /* x should be integral */ + /* y should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(yy); + mpq2mpz(yy,*y,NOISY); + + mpz_init(res); + +#if 0 + mpz_xor(res,xx,yy); +#else /* 0 */ + /* a^b = (a|b) & !(a&b) */ + { + mpz_t and_ab, ior_ab, nand_ab; + + mpz_init(ior_ab); + mpz_ior(ior_ab,xx,yy); + + mpz_init(and_ab); + mpz_and(and_ab,xx,yy); + + mpz_init(nand_ab); + mpz_com(nand_ab,and_ab); + + mpz_and(res,ior_ab,nand_ab); + + mpz_clear(and_ab); + mpz_clear(ior_ab); + mpz_clear(nand_ab); + } +#endif /* 0 */ + + mpz_clear(xx); + mpz_clear(yy); + + mpz2mpq(*x,res); + mpz_clear(res); +} + +void +numb_not(eval_t *x) +{ + mpz_t xx, res; + + /* x should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(res); + mpz_com(res,xx); + + mpz_clear(xx); + + mpz2mpq(*x,res); + mpz_clear(res); +} + +void +numb_lshift(eval_t *x, const eval_t *y) +{ + mpz_t xx, yy, res; + + /* x should be integral */ + /* y should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(yy); + mpq2mpz(yy,*y,NOISY); + + mpz_init(res); + { /* bug: need to determine if y is too big or negative */ + long int exp = mpz_get_si(yy); + if (exp >= 0) { + mpz_mul_2exp(res,xx,(unsigned)exp); + } else { + mpz_div_2exp(res,xx,(unsigned)-exp); + } + } + + mpz_clear(xx); + mpz_clear(yy); + + mpz2mpq(*x,res); + mpz_clear(res); +} + +void +numb_rshift(eval_t *x, const eval_t *y) +{ + mpz_t xx, yy, res; + + /* x should be integral */ + /* y should be integral */ + + mpz_init(xx); + mpq2mpz(xx,*x,NOISY); + + mpz_init(yy); + mpq2mpz(yy,*y,NOISY); + + mpz_init(res); + { /* bug: need to determine if y is too big or negative */ + long int exp = mpz_get_si(yy); + if (exp >= 0) { + mpz_div_2exp(res,xx,(unsigned)exp); + } else { + mpz_mul_2exp(res,xx,(unsigned)-exp); + } + } + + mpz_clear(xx); + mpz_clear(yy); + + mpz2mpq(*x,res); + mpz_clear(res); +} + + +#else /* WITH_GMP */ + +void +numb_initialise(void) +{ + ; +} + + +/*------------------------------------------------------------------------. +| The function ntoa () converts VALUE to a signed ascii representation in | +| radix RADIX. | +`------------------------------------------------------------------------*/ + +/* Digits for number to ascii conversions. */ +static char const ntoa_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +static const char * +ntoa (eval_t value, int radix) +{ + boolean negative; + ueval_t uvalue; + static char str[256]; + register char *s = &str[sizeof str]; + + *--s = '\0'; + + if (value < 0) + { + negative = TRUE; + uvalue = (ueval_t) -value; + } + else + { + negative = FALSE; + uvalue = (ueval_t) value; + } + + do + { + *--s = ntoa_digits[uvalue % radix]; + uvalue /= radix; + } + while (uvalue > 0); + + if (negative) + *--s = '-'; + return s; +} + +void +numb_obstack(struct obstack *obs, const eval_t value, + const int radix, int min) +{ + const char *s = ntoa (value, radix); + + if (*s == '-') + { + obstack_1grow (obs, '-'); + min--; + s++; + } + for (min -= strlen (s); --min >= 0;) + obstack_1grow (obs, '0'); + + obstack_grow (obs, s, strlen (s)); +} + + +#endif /* WITH_GMP */ + + +void +numb_pow (eval_t *x, const eval_t *y) +{ + /* y should be integral */ + + eval_t ans, yy; + + numb_init(ans); + numb_set_si(&ans,1); + + numb_init(yy); + numb_set(yy,*y); + + if (numb_negativep(yy)) { + numb_invert(*x); + numb_negate(yy); + } + + while (numb_positivep(yy)) { + numb_times(ans,*x); + numb_decr(yy); + } + numb_set(*x,ans); + + numb_fini(ans); + numb_fini(yy); +} diff --git a/src/numb.h b/src/numb.h new file mode 100644 index 00000000..2fa02a58 --- /dev/null +++ b/src/numb.h @@ -0,0 +1,156 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "m4.h" + +#ifdef WITH_GMP +#define NUMB_MP 1 +#endif + +#ifdef WITH_GMP +#include "gmp.h" + +/* eval_t should be at least 32 bits. */ +typedef mpq_t eval_t; + +extern eval_t numb_ZERO; +extern eval_t numb_ONE; + +#define numb_set(ans,i) mpq_set(ans,i) +#define numb_set_si(ans,i) mpq_set_si(*(ans),(long)i,(unsigned long)1) + +#define numb_init(x) mpq_init((x)) +#define numb_fini(x) mpq_clear((x)) + +#define numb_zerop(x) (mpq_cmp(x,numb_ZERO) == 0) +#define numb_positivep(x) (mpq_cmp(x,numb_ZERO) > 0) +#define numb_negativep(x) (mpq_cmp(x,numb_ZERO) < 0) + +#define numb_eq(x,y) numb_set(x,mpq_cmp(x,y)==0? numb_ONE: numb_ZERO) +#define numb_ne(x,y) numb_set(x,mpq_cmp(x,y)!=0? numb_ONE: numb_ZERO) +#define numb_lt(x,y) numb_set(x,mpq_cmp(x,y)< 0? numb_ONE: numb_ZERO) +#define numb_le(x,y) numb_set(x,mpq_cmp(x,y)<=0? numb_ONE: numb_ZERO) +#define numb_gt(x,y) numb_set(x,mpq_cmp(x,y)> 0? numb_ONE: numb_ZERO) +#define numb_ge(x,y) numb_set(x,mpq_cmp(x,y)>=0? numb_ONE: numb_ZERO) + +#define numb_lnot(x) numb_set(x,numb_zerop(x)? numb_ONE: numb_ZERO) +#define numb_lior(x,y) numb_set(x,numb_zerop(x)? y: numb_ONE) +#define numb_land(x,y) numb_set(x,numb_zerop(x)? numb_ZERO: y) + +#define reduce1(f1,x) \ +{ eval_t T; mpq_init(T); f1(T,x); mpq_set(x,T); mpq_clear(T); } +#define reduce2(f2,x,y) \ +{ eval_t T; mpq_init(T); f2(T,(x),(y)); mpq_set((x),T); mpq_clear(T); } + +#define numb_plus(x,y) reduce2(mpq_add,x,y) +#define numb_minus(x,y) reduce2(mpq_sub,x,y) +#define numb_negate(x) reduce1(mpq_neg,x) + +#define numb_times(x,y) reduce2(mpq_mul,x,y) +#define numb_ratio(x,y) reduce2(mpq_div,x,y) +#define numb_invert(x) reduce1(mpq_inv,x) + +#define numb_decr(n) numb_minus(n,numb_ONE) + + + +void numb_divide(eval_t *x, const eval_t *y); +void numb_modulo(eval_t *x, const eval_t *y); +void numb_and(eval_t *x, const eval_t *y); +void numb_ior(eval_t *x, const eval_t *y); +void numb_eor(eval_t *x, const eval_t *y); +void numb_not(eval_t *x);; +void numb_lshift(eval_t *x, const eval_t *y); +void numb_rshift(eval_t *x, const eval_t *y); +void numb_pow (eval_t *x, const eval_t *y); + + + + +#else /* not WITH_GMP */ + +/* eval_t should be at least 32 bits. */ +/* use GNU long long int if available */ +#if defined(SIZEOF_LONG_LONG_INT) && SIZEOF_LONG_LONG_INT > 0 +typedef long long int eval_t; +typedef unsigned long long int ueval_t; +#else +typedef long int eval_t; +typedef unsigned long int ueval_t; +#endif + +extern eval_t numb_ZERO; +extern eval_t numb_ONE; + +#define int2numb(i) ((eval_t)(i)) +#define numb2int(n) ((n)) + +#define numb_set(ans,x) ((ans) = x) +#define numb_set_si(ans,si) (*(ans) = int2numb(si)) + +#define numb_init(x) x=((eval_t)0) +#define numb_fini(x) + +#define numb_decr(n) (n) -= 1 + +#define numb_ZERO ((eval_t)0) +#define numb_ONE ((eval_t)1) + +#define numb_zerop(x) ((x) == numb_ZERO) +#define numb_positivep(x) ((x) > numb_ZERO) +#define numb_negativep(x) ((x) < numb_ZERO) + + +#define numb_eq(x,y) ((x) = ((x) == (y))) +#define numb_ne(x,y) ((x) = ((x) != (y))) +#define numb_lt(x,y) ((x) = ((x) < (y))) +#define numb_le(x,y) ((x) = ((x) <= (y))) +#define numb_gt(x,y) ((x) = ((x) > (y))) +#define numb_ge(x,y) ((x) = ((x) >= (y))) + +#define numb_lnot(x) ((x) = (! (x))) +#define numb_lior(x,y) ((x) = ((x) || (y))) +#define numb_land(x,y) ((x) = ((x) && (y))) + +#define numb_not(x) (*(x) = int2numb(~numb2int(*(x)))) +#define numb_eor(x,y) (*(x) = int2numb(numb2int(*(x)) ^ numb2int(*(y)))) +#define numb_ior(x,y) (*(x) = int2numb(numb2int(*(x)) | numb2int(*(y)))) +#define numb_and(x,y) (*(x) = int2numb(numb2int(*(x)) & numb2int(*(y)))) + +#define numb_plus(x,y) ((x) = ((x) + (y))) +#define numb_minus(x,y) ((x) = ((x) - (y))) +#define numb_negate(x) ((x) = (- (x))) + +#define numb_times(x,y) ((x) = ((x) * (y))) +#define numb_ratio(x,y) ((x) = ((x) / ((y)))) +#define numb_divide(x,y) (*(x) = (*(x) / (*(y)))) +#define numb_modulo(x,y) (*(x) = (*(x) % *(y))) +#define numb_invert(x) ((x) = 1 / (x)) + +#define numb_lshift(x,y) (*(x) = (*(x) << *(y))) +#define numb_rshift(x,y) (*(x) = (*(x) >> *(y))) + +void numb_pow (eval_t *x, const eval_t *y); + +#endif /* WITH_GMP */ + + +void numb_initialise __P((void)); +void numb_obstack __P((struct obstack *obs, + const eval_t value, + const int radix, int min)); diff --git a/src/output.c b/src/output.c new file mode 100644 index 00000000..fdf8795b --- /dev/null +++ b/src/output.c @@ -0,0 +1,590 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "m4.h" + +#include <sys/stat.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) + +#ifdef HAVE_TMPFILE +extern FILE *tmpfile (); +#endif + +/* 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? */ + +/* In a struct diversion, only one of file or buffer be may non-NULL, + depending on the fact output is diverted to a file or in memory + buffer. Further, if buffer is NULL, then pointer is NULL, size and + unused are zero. */ + +struct diversion + { + FILE *file; /* diversion file on disk */ + char *buffer; /* in-memory diversion buffer */ + int size; /* usable size before reallocation */ + int used; /* used length in characters */ + }; + +/* Table of diversions. */ +static struct diversion *diversion_table; + +/* Number of entries in diversion table. */ +static int diversions; + +/* 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 struct 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; + +/*------------------------. +| Output initialisation. | +`------------------------*/ + +void +output_init (void) +{ + diversion_table = (struct diversion *) xmalloc (sizeof (struct diversion)); + diversions = 1; + diversion_table[0].file = stdout; + diversion_table[0].buffer = NULL; + diversion_table[0].size = 0; + diversion_table[0].used = 0; + + total_buffer_size = 0; + current_diversion = 0; + output_diversion = diversion_table; + output_file = stdout; + output_cursor = NULL; + output_unused = 0; +} + +#ifndef HAVE_TMPFILE + +#ifndef HAVE_MKSTEMP + +/* This implementation of mkstemp(3) does not avoid any races, but its + there. */ + +#include <fcntl.h> + +static int +mkstemp (const char *tmpl) +{ + mktemp (tmpl); + return open (tmpl, O_RDWR | O_TRUNC | O_CREAT, 0600); +} + +#endif /* not HAVE_MKSTEMP */ + +/* Implement tmpfile(3) for non-USG systems. */ + +static FILE * +tmpfile (void) +{ + char buf[32]; + int fd; + + strcpy (buf, "/tmp/m4XXXXXX"); + fd = mkstemp (buf); + if (fd < 0) + return NULL; + + unlink (buf); + return fdopen (fd, "w+"); +} + +#endif /* not HAVE_TMPFILE */ + +/*-----------------------------------------------------------------------. +| 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; + + /* 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) + { + struct diversion *selected_diversion; + int selected_used; + struct diversion *diversion; + int count; + + /* 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; + + for (diversion = diversion_table + 1; + diversion < diversion_table + diversions; + diversion++) + if (diversion->used > selected_used) + { + selected_diversion = diversion; + selected_used = diversion->used; + } + + /* Create a temporary file, write the in-memory buffer of the + diversion to this file, then release the buffer. */ + + selected_diversion->file = tmpfile (); + if (selected_diversion->file == NULL) + M4ERROR ((EXIT_FAILURE, errno, + "ERROR: Cannot create temporary file for diversion")); + + if (selected_diversion->used > 0) + { + count = fwrite (selected_diversion->buffer, + (size_t) selected_diversion->used, + 1, + selected_diversion->file); + if (count != 1) + M4ERROR ((EXIT_FAILURE, errno, + "ERROR: Cannot flush diversion to temporary file")); + } + + /* Reclaim the buffer space for other diversions. */ + + free (selected_diversion->buffer); + total_buffer_size -= selected_diversion->size; + + selected_diversion->buffer = NULL; + selected_diversion->size = 0; + selected_diversion->used = 0; + } + + /* Reload output_file, just in case the flushed diversion was current. */ + + output_file = output_diversion->file; + if (output_file) + { + + /* The flushed diversion was current indeed. */ + + output_cursor = NULL; + output_unused = 0; + } + else + { + + /* The buffer may be safely reallocated. */ + + output_diversion->buffer + = xrealloc (output_diversion->buffer, (size_t) wanted_size); + + total_buffer_size += wanted_size - output_diversion->size; + output_diversion->size = wanted_size; + + output_cursor = output_diversion->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 boolean 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' synchronisation 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) + { + 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) +{ + struct diversion *diversion; + + if (output_diversion) + { + output_diversion->file = output_file; + output_diversion->used = output_diversion->size - output_unused; + output_diversion = NULL; + output_file = NULL; + output_cursor = NULL; + output_unused = 0; + } + + current_diversion = divnum; + + if (divnum < 0) + return; + + if (divnum >= diversions) + { + diversion_table = (struct diversion *) + xrealloc (diversion_table, (divnum + 1) * sizeof (struct diversion)); + for (diversion = diversion_table + diversions; + diversion <= diversion_table + divnum; + diversion++) + { + diversion->file = NULL; + diversion->buffer = NULL; + diversion->size = 0; + diversion->used = 0; + } + diversions = divnum + 1; + } + + output_diversion = diversion_table + divnum; + output_file = output_diversion->file; + output_cursor = output_diversion->buffer + output_diversion->used; + output_unused = output_diversion->size - output_diversion->used; + 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. */ + + while (length = read (fileno (file), buffer, COPY_BUFFER_SIZE), + length != 0) + if (length == (size_t) -1) + M4ERROR ((EXIT_FAILURE, errno, "ERROR: Reading inserted file")); + else + output_text (buffer, length); +} + +/*-------------------------------------------------------------------------. +| 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) +{ + struct diversion *diversion; + + /* Do not care about unexisting diversions. */ + + if (divnum < 0 || divnum >= diversions) + return; + + /* Also avoid undiverting into self. */ + + diversion = diversion_table + divnum; + if (diversion == output_diversion) + return; + + /* Effectively undivert only if an output stream is active. */ + + if (output_diversion) + { + if (diversion->file) + { + rewind (diversion->file); + insert_file (diversion->file); + } + else if (diversion->buffer) + output_text (diversion->buffer, diversion->used); + + output_current_line = -1; + } + + /* Return all space used by the diversion. */ + + if (diversion->file) + { + fclose (diversion->file); + diversion->file = NULL; + } + else if (diversion->buffer) + { + free (diversion->buffer); + diversion->buffer = NULL; + diversion->size = 0; + diversion->used = 0; + } +} + +/*-------------------------------------------------------------------------. +| Get back all diversions. This is done just before exiting from main (), | +| and from m4_undivert (), if called without arguments. | +`-------------------------------------------------------------------------*/ + +void +undivert_all (void) +{ + int divnum; + + for (divnum = 1; divnum < diversions; divnum++) + insert_diversion (divnum); +} + +/*-------------------------------------------------------------. +| Produce all diversion information in frozen format on FILE. | +`-------------------------------------------------------------*/ + +void +freeze_diversions (FILE *file) +{ + int saved_number; + int last_inserted; + int divnum; + struct diversion *diversion; + struct stat file_stat; + + saved_number = current_diversion; + last_inserted = 0; + make_diversion (0); + output_file = file; /* kludge in the frozen file */ + + for (divnum = 1; divnum < diversions; divnum++) + { + diversion = diversion_table + divnum; + if (diversion->file || diversion->buffer) + { + if (diversion->file) + { + fflush (diversion->file); + if (fstat (fileno (diversion->file), &file_stat) < 0) + M4ERROR ((EXIT_FAILURE, errno, "Cannot stat diversion")); + fprintf (file, "D%d,%d", divnum, (int) file_stat.st_size); + } + else + fprintf (file, "D%d,%d\n", divnum, diversion->used); + + insert_diversion (divnum); + putc ('\n', file); + + last_inserted = divnum; + } + } + + /* 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/path.c b/src/path.c new file mode 100644 index 00000000..90bdc6de --- /dev/null +++ b/src/path.c @@ -0,0 +1,151 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93 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., 675 Mass Ave, Cambridge, MA 02139, 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; + + if (no_gnu_extensions) + return; + + path = getenv ("M4PATH"); + if (path == NULL) + return; + + do + { + path_end = strchr (path, ':'); + if (path_end) + *path_end = '\0'; + add_include_directory (path); + path = path_end + 1; + } + while (path_end); +} + +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 +} + +FILE * +path_search (const char *dir) +{ + FILE *fp; + includes *incl; + char *name; /* buffer for constructed name */ + + /* Look in current working directory first. */ + fp = fopen (dir, "r"); + if (fp != NULL) + return fp; + + /* If file not found, and filename absolute, fail. */ + if (*dir == '/' || no_gnu_extensions) + return NULL; + + name = (char *) xmalloc (dir_max_length + 1 + strlen (dir) + 1); + + for (incl = dir_list; incl != NULL; incl = incl->next) + { + strncpy (name, incl->dir, incl->len); + name[incl->len] = '/'; + strcpy (name + incl->len + 1, dir); + +#ifdef DEBUG_INCL + fprintf (stderr, "path_search (%s) -- trying %s\n", dir, name); +#endif + + fp = fopen (name, "r"); + if (fp != NULL) + { + if (debug_level & DEBUG_TRACE_PATH) + DEBUG_MESSAGE (("path search for `%s' found `%s'", dir, name)); + break; + } + } + xfree (name); + return fp; +} + +#ifdef DEBUG_INCL + +static int +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/stackovf.c b/src/stackovf.c new file mode 100644 index 00000000..10d3851e --- /dev/null +++ b/src/stackovf.c @@ -0,0 +1,392 @@ +/* Detect stack overflow (when getrlimit and sigaction or sigvec are available) + Copyright (C) 1993, 1994 Free Software Foundation, Inc. + Jim Avera <jima@netcom.com>, 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, 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., 675 Mass Ave, Cambridge, MA 02139, 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 <siginfo.h> or another way to determine + the fault address. + + There is no completely portable way to determine if a SIGSEGV signal + indicates a stack overflow. The fault address can be used to infer + this. However, the fault address is passed to the signal handler in + different ways on various systems. One of three methods are used to + determine the fault address: + + 1. The siginfo parameter (with siginfo.h, i.e., SVR4). + + 2. 4th "addr" parameter (assumed if struct sigcontext is defined, + i.e., SunOS 4.x/BSD). + + 3. None (if no method is available). This case just prints a + message before aborting with a core dump. That way the user at + least knows that it *might* be a recursion problem. + + Jim Avera <jima@netcom.com> 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 <jima@netcom.com> 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 <jima@netcom.com> writes, on Wed, 6 Jul 1994 14:41 PDT: + + "When a stack overflow occurs, a SIGSEGV signal is sent, which by + default aborts the process with a core dump. + + The code in stackovf.c catches SIGSEGV using a separate signal + stack. The signal handler determines whether or not the SIGSEGV + arose from a stack overflow. If it is a stack overflow, an + external function is called (which, in m4, prints a message an + exits). Otherwise the SIGSEGV represents an m4 bug, and the signal + is re-raised with SIG_DFL set, which results in an abort and core + dump in the usual way. It seems important (to me) that internal m4 + bugs not be reported as user recursion errors, or vice-versa." */ + +#define DEBUG_STACKOVF + +#include "m4.h" /* stdlib.h, xmalloc() */ + +#include <assert.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <signal.h> + +#if HAVE_SIGINFO_H +# include <siginfo.h> +#endif + +#ifndef 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 + +/* Giving a hand to ansi2knr... */ +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) +#define PARAM_NOSTACKOVF ((const char *) 2) + +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_SIGINFO_H + +/* SVR4. */ + +static void +sigsegv_handler (int signo, siginfo_t * ip) +{ + process_sigsegv + (signo, (ip != (siginfo_t *) 0 + && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL)); +} + +#else /* not HAVE_SIGINFO_H */ +#if 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 */ +#endif /* not HAVE_SIGINFO */ + +/* 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; +#else + struct sigvec vec; +#endif + + grows_upward = ((char *) argv < (char *) &stack_len); + arg0 = argv[0]; + stackovf_handler = handler; + + /* Calculate the approximate expected addr for a stack-ovf trap. */ + + if (getrlimit (RLIMIT_STACK, &rl) < 0) + error (1, 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) != (char *) 0; v++) + { + if (p < stackbot) + stackbot = p; + } + if ((char *) envp < stackbot) + stackbot = (char *) envp; + for (v = envp; (p = (char *) *v) != (char *) 0; v++) + { + if (p < stackbot) + stackbot = p; + } + stackend = stackbot + stack_len; + } + else + { + + /* The stack grows "downward" (toward decreasing addresses). */ + + for (v = argv; (p = (char *) *v) != (char *) 0; v++) + { + if (p > stackbot) + stackbot = p; + } + if ((char *) envp > stackbot) + stackbot = (char *) envp; + for (v = envp; (p = (char *) *v) != (char *) 0; v++) + { + if (p > stackbot) + stackbot = p; + } + stackend = stackbot - stack_len; + } + + /* Allocate a separate signal-handler stack. */ + +#if HAVE_SIGALTSTACK && (defined(HAVE_SIGINFO_H) || !HAVE_SIGSTACK) + + /* Use sigaltstack only if siginfo 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, (stack_t *) 0) < 0) + error (1, errno, "sigaltstack"); + } + +#else /* not HAVE_SIGALTSTACK || not HAVE_SIGINFO_H && HAVE_SIGSTACK */ +#if HAVE_SIGSTACK + + { + struct sigstack ss; + char *stackbuf = xmalloc (2 * SIGSTKSZ); + + ss.ss_sp = stackbuf + SIGSTKSZ; + ss.ss_onstack = 0; + if (sigstack (&ss, NULL) < 0) + error (1, errno, "sigstack"); + } + +#else /* not HAVE_SIGSTACK */ + +Error - Do not know how to set up stack-ovf trap handler... + +#endif /* not HAVE_SIGSTACK */ +#endif /* not HAVE_SIGALTSTACK || not HAVE_SIGINFO_H && HAVE_SIGSTACK */ + + /* Arm the SIGSEGV signal handler. */ + +#if HAVE_SIGACTION && defined(SA_ONSTACK) + + sigaction (SIGSEGV, NULL, &act); + act.sa_handler = (RETSIGTYPE (*) _((int))) sigsegv_handler; + sigemptyset (&act.sa_mask); + act.sa_flags = (SA_ONSTACK +#ifdef SA_RESETHAND + | SA_RESETHAND +#endif +#ifdef SA_SIGINFO + | SA_SIGINFO +#endif + ); + if (sigaction (SIGSEGV, &act, NULL) < 0) + error (1, errno, "sigaction"); + +#else /* not HAVE_SIGACTION */ +#if HAVE_SIGVEC && defined(SV_ONSTACK) + + vec.sv_handler = (RETSIGTYPE (*)_ ((int))) sigsegv_handler; + vec.sv_mask = 0; + vec.sv_flags = (SV_ONSTACK +#ifdef SV_RESETHAND + | SV_RESETHAND +#endif + ); + if (sigvec (SIGSEGV, &vec, NULL) < 0) + error (1, errno, "sigvec"); + +#else /* not HAVE_SIGVEC && defined(SV_ONSTACK) */ + +Error - Do not know how to catch signals on an alternate stack... + +#endif /* HAVE_SIGVEC && defined(SV_ONSTACK) */ +#endif /* HAVE_SIGALTSTACK && defined(SA_ONSTACK) */ + +} diff --git a/src/symtab.c b/src/symtab.c new file mode 100644 index 00000000..150a84bf --- /dev/null +++ b/src/symtab.c @@ -0,0 +1,266 @@ +/* GNU m4 -- A simple macro processor + Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/*----------------------------------------------------------------------. +| Initialise the symbol table, by allocating the necessary storage, and | +| zeroing all the entries. | +`----------------------------------------------------------------------*/ + +/* Pointer to symbol table. */ +symbol **symtab; + +void +symtab_init (void) +{ + int i; + symbol **s; + + s = symtab = (symbol **) xmalloc (hash_table_size * sizeof (symbol *)); + + for (i = hash_table_size; --i >= 0;) + *s++ = NULL; +} + +/*--------------------------------------------------. +| Return a hashvalue for a string, from GNU-emacs. | +`--------------------------------------------------*/ + +static int +hash (const char *s) +{ + register int val = 0; + + register const char *ptr = s; + register char ch; + + while ((ch = *ptr++) != '\0') + { + if (ch >= 0140) + ch -= 40; + val = ((val << 3) + (val >> 28) + ch); + }; + val = (val < 0) ? -val : val; + return val % hash_table_size; +} + +/*--------------------------------------------. +| Free all storage associated with a symbol. | +`--------------------------------------------*/ + +static void +free_symbol (symbol *sym) +{ + if (SYMBOL_NAME (sym)) + xfree (SYMBOL_NAME (sym)); + if (SYMBOL_TYPE (sym) == TOKEN_TEXT) + xfree (SYMBOL_TEXT (sym)); + xfree ((voidstar) 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 searched this list for the first occurence 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 occurences of the name | +| on the list. | +`------------------------------------------------------------------------*/ + +symbol * +lookup_symbol (const char *name, symbol_lookup mode) +{ + int h, cmp = 1; + symbol *sym, *prev; + symbol **spp; + + h = hash (name); + sym = symtab[h]; + + 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]; + + switch (mode) + { + + case SYMBOL_INSERT: + + /* Return the symbol, if the name was found in the table. + Otherwise, just insert the name, and return the new symbol. */ + + if (cmp == 0 && sym != NULL) + 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) = SYMBOL_SHADOWED (sym) = FALSE; + SYMBOL_NAME (sym) = xstrdup (name); + + 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: + + /* Delete all occurences of symbols with NAME. */ + + if (cmp != 0 || sym == NULL) + return NULL; + do + { + *spp = SYMBOL_NEXT (sym); + free_symbol (sym); + sym = *spp; + } + while (sym != NULL && strcmp (name, SYMBOL_NAME (sym)) == 0); + return NULL; + + case SYMBOL_POPDEF: + + /* Delete the first occurence of a symbol with NAME. */ + + if (cmp != 0 || sym == NULL) + return NULL; + if (SYMBOL_NEXT (sym) != NULL && cmp == 0) + SYMBOL_SHADOWED (SYMBOL_NEXT (sym)) = FALSE; + *spp = SYMBOL_NEXT (sym); + free_symbol (sym); + return NULL; + + default: + M4ERROR ((warning_status, 0, + "INTERNAL ERROR: Illegal 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. | +`----------------------------------------------------------------------*/ + +void +hack_all_symbols (hack_symbol *func, const char *data) +{ + int h; + symbol *sym; + + for (h = 0; h < hash_table_size; h++) + { + for (sym = symtab[h]; sym != NULL; sym = SYMBOL_NEXT (sym)) + (*func) (sym, data); + } +} + +#ifdef DEBUG_SYM + +static void +symtab_debug (void) +{ + token_type t; + token_data td; + const char *text; + symbol *s; + int delete; + + while ((t = next_token (&td)) != NULL) + { + if (t != TOKEN_WORD) + continue; + 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); + } + hack_all_symbols (dump_symbol); +} + +static void +symtab_print_list (int i) +{ + symbol *sym; + + printf ("Symbol dump #d:\n", i); + for (sym = symtab[i]; sym != NULL; sym = sym->next) + printf ("\tname %s, addr 0x%x, next 0x%x, flags%s%s\n", + SYMBOL_NAME (sym), sym, sym->next, + SYMBOL_TRACED (sym) ? " traced" : "", + SYMBOL_SHADOWED (sym) ? " shadowed" : ""); +} + +#endif /* DEBUG_SYM */ diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 00000000..aa5b9250 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +Sat Nov 5 22:45:51 EST 1994 diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..7aed6dc3 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,35 @@ +# The next line is needed by `./esyscmd.1.test' +# Ty Coon, President of Vice +# The previous line is needed by `./esyscmd.1.test' + +EXTRA_DIST = get-them foo incl.m4 stamp-TESTS $(TESTS) defs m4wrap.1.test + +TESTS = $(OTHER_TESTS) $(GENERATED_TESTS) + +GENERATED_TESTS = \ + argument.1.test argument.2.test argument.3.test argument.4.test \ + changeco.1.test changeco.2.test changequ.1.test changequ.2.test \ + changequ.3.test changesy.1.test changesy.2.test changesy.3.test \ + changesy.4.test changesy.5.test changesy.6.test changesy.7.test \ + cleardiv.1.test cleardiv.2.test define.1.test define.2.test \ + defn.1.test defn.2.test divert.1.test divert.2.test divnum.1.test \ + dnl.1.test dumpdef.1.test errprint.1.test errprint.2.test \ + esyscmd.1.test eval.1.test eval.2.test format.1.test ifdef.1.test \ + ifelse.1.test ifelse.2.test include.1.test include.2.test \ + include.3.test incr.1.test index.1.test indir.1.test len.1.test \ + loops.1.test loops.2.test m4exit.1.test patsubst.1.test \ + patsubst.2.test pseudoar.1.test pseudoar.2.test pseudoar.3.test \ + pseudoar.4.test pseudoar.5.test pushdef.1.test pushdef.2.test \ + regexp.1.test regexp.2.test substr.1.test sysval.1.test trace.1.test \ + translit.1.test undefine.1.test undivert.1.test undivert.2.test \ + undivert.3.test + +OTHER_TESTS = + +all: stamp-TESTS + +stamp-TESTS: $(srcdir)/get-them $(top_srcdir)/doc/m4.texinfo + cd $(srcdir) \ + && rm -f *.[0-9].test \ + && AWK=$(AWK) $(srcdir)/get-them $(top_srcdir)/doc/m4.texinfo \ + && > $@ diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 00000000..e8f24129 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,235 @@ +# Makefile.in generated automatically by automake 1.3b from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 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. + +# The next line is needed by `./esyscmd.1.test' +# Ty Coon, President of Vice +# The previous line is needed by `./esyscmd.1.test' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +PACKAGE = @PACKAGE@ +PERL = @PERL@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +STACKOVF = @STACKOVF@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +l = @l@ + +EXTRA_DIST = get-them foo incl.m4 stamp-TESTS $(TESTS) defs m4wrap.1.test + +TESTS = $(OTHER_TESTS) $(GENERATED_TESTS) + +GENERATED_TESTS = \ + argument.1.test argument.2.test argument.3.test argument.4.test \ + changeco.1.test changeco.2.test changequ.1.test changequ.2.test \ + changequ.3.test changesy.1.test changesy.2.test changesy.3.test \ + changesy.4.test changesy.5.test changesy.6.test changesy.7.test \ + cleardiv.1.test cleardiv.2.test define.1.test define.2.test \ + defn.1.test defn.2.test divert.1.test divert.2.test divnum.1.test \ + dnl.1.test dumpdef.1.test errprint.1.test errprint.2.test \ + esyscmd.1.test eval.1.test eval.2.test format.1.test ifdef.1.test \ + ifelse.1.test ifelse.2.test include.1.test include.2.test \ + include.3.test incr.1.test index.1.test indir.1.test len.1.test \ + loops.1.test loops.2.test m4exit.1.test patsubst.1.test \ + patsubst.2.test pseudoar.1.test pseudoar.2.test pseudoar.3.test \ + pseudoar.4.test pseudoar.5.test pushdef.1.test pushdef.2.test \ + regexp.1.test regexp.2.test substr.1.test sysval.1.test trace.1.test \ + translit.1.test undefine.1.test undivert.1.test undivert.2.test \ + undivert.3.test + +OTHER_TESTS = +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps tests/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = tests + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +check-TESTS: $(TESTS) + @failed=0; all=0; \ + srcdir=$(srcdir); export srcdir; \ + for tst in $(TESTS); do \ + if test -f $$tst; then dir=.; \ + else dir="$(srcdir)"; fi; \ + if $(TESTS_ENVIRONMENT) $$dir/$$tst; then \ + all=`expr $$all + 1`; \ + echo "PASS: $$tst"; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="$$failed of $$all tests failed"; \ + fi; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0 +info: +dvi: +check: all + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir check-TESTS info dvi installcheck install-exec \ +install-data install uninstall all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +all: stamp-TESTS + +stamp-TESTS: $(srcdir)/get-them $(top_srcdir)/doc/m4.texinfo + cd $(srcdir) \ + && rm -f *.[0-9].test \ + && AWK=$(AWK) $(srcdir)/get-them $(top_srcdir)/doc/m4.texinfo \ + && > $@ + +# 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/tests/argument.1.test b/tests/argument.1.test new file mode 100755 index 00000000..9398608f --- /dev/null +++ b/tests/argument.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# argument.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1037 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +exch(arg1, arg2) +EOF + +cat <<\EOF >ok + +arg2, arg1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/argument.2.test b/tests/argument.2.test new file mode 100755 index 00000000..abd434f3 --- /dev/null +++ b/tests/argument.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# argument.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1047 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +define(exch(``expansion text'', ``macro'')) +macro +EOF + +cat <<\EOF >ok + + +expansion text +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/argument.3.test b/tests/argument.3.test new file mode 100755 index 00000000..0231981b --- /dev/null +++ b/tests/argument.3.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# argument.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1067 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', ``Macro name: $0'') +test +EOF + +cat <<\EOF >ok + +Macro name: test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/argument.4.test b/tests/argument.4.test new file mode 100755 index 00000000..a0c5cbfd --- /dev/null +++ b/tests/argument.4.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# argument.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1077 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `This is macro `foo'.') +foo +EOF + +cat <<\EOF >ok + +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changeco.1.test b/tests/changeco.1.test new file mode 100755 index 00000000..d1a60b0c --- /dev/null +++ b/tests/changeco.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# changeco.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1960 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +# A normal comment +changecom(`/*', `*/') +# Not a comment anymore +But: /* this is a comment now */ while this is not a comment +EOF + +cat <<\EOF >ok + +# A normal comment + +# Not a COMMENT anymore +But: /* this is a comment now */ while this is not a COMMENT +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changeco.2.test b/tests/changeco.2.test new file mode 100755 index 00000000..21854f26 --- /dev/null +++ b/tests/changeco.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# changeco.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1981 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +changecom +# Not a comment anymore +EOF + +cat <<\EOF >ok + + +# Not a COMMENT anymore +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changequ.1.test b/tests/changequ.1.test new file mode 100755 index 00000000..4e6f1fa6 --- /dev/null +++ b/tests/changequ.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# changequ.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1896 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([, ]) +define([foo], [Macro [foo].]) +foo +EOF + +cat <<\EOF >ok + + +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changequ.2.test b/tests/changequ.2.test new file mode 100755 index 00000000..45fd0dbe --- /dev/null +++ b/tests/changequ.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# changequ.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1908 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([[, ]]) +define([[foo]], [[Macro [[[foo]]].]]) +foo +EOF + +cat <<\EOF >ok + + +Macro [foo]. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changequ.3.test b/tests/changequ.3.test new file mode 100755 index 00000000..d9432142 --- /dev/null +++ b/tests/changequ.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# changequ.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1920 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `FOO'.') +changequote(, ) +foo +`foo' +EOF + +cat <<\EOF >ok + + +Macro `FOO'. +`Macro `FOO'.' +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.1.test b/tests/changesy.1.test new file mode 100755 index 00000000..76512aae --- /dev/null +++ b/tests/changesy.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# changesy.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2126 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test.1', `TEST ONE') +__file__ +changesyntax(`O_', `W.') +__file__ +test.1 +EOF + +cat <<\EOF >ok + +in + +__file__ +TEST ONE +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.2.test b/tests/changesy.2.test new file mode 100755 index 00000000..d34dbb29 --- /dev/null +++ b/tests/changesy.2.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# changesy.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2142 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$#') +test(a, b, c) +changesyntax(`(<', `,|', `)>', `O(,)') +test(a, b, c) +test<a|b|c> +EOF + +cat <<\EOF >ok + +3 + +0(a, b, c) +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.3.test b/tests/changesy.3.test new file mode 100755 index 00000000..15a51f77 --- /dev/null +++ b/tests/changesy.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# changesy.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2159 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$1$2$3') +test(a, b, c) +changesyntax(`O ') +test(a, b, c) +EOF + +cat <<\EOF >ok + +abc + +a b c +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.4.test b/tests/changesy.4.test new file mode 100755 index 00000000..5dcde934 --- /dev/null +++ b/tests/changesy.4.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# changesy.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2178 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`@', `TEST') +@ +changesyntax(`A@') +@ +EOF + +cat <<\EOF >ok + +@ + +TEST +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.5.test b/tests/changesy.5.test new file mode 100755 index 00000000..1156668f --- /dev/null +++ b/tests/changesy.5.test @@ -0,0 +1,31 @@ +#!/bin/sh + +# changesy.5.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2202 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `TEST') +changesyntax(`L<', `R>') +<test> +`test> +changequote(<[>, `]') +<test> +[test] +EOF + +cat <<\EOF >ok + + +test +test + +<TEST> +test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.6.test b/tests/changesy.6.test new file mode 100755 index 00000000..cae2ee23 --- /dev/null +++ b/tests/changesy.6.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# changesy.6.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2224 + +. ${srcdir}/defs + +cat <<\EOF >in +changesyntax(`({<', `)}>', `,;:', `O(,)') +eval{2**4-1; 2 : 8> +EOF + +cat <<\EOF >ok + +00001111 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/changesy.7.test b/tests/changesy.7.test new file mode 100755 index 00000000..9d4b4b08 --- /dev/null +++ b/tests/changesy.7.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# changesy.7.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2235 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `==$1==') +changequote(`<<', `>>') +changesyntax(<<L[>>, <<R]>>) +test(<<testing]>>) +test([testing>>]) +test([<<testing>>]) +EOF + +cat <<\EOF >ok + + + +==testing]== +==testing>>== +==<<testing>>== +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/cleardiv.1.test b/tests/cleardiv.1.test new file mode 100755 index 00000000..40f09405 --- /dev/null +++ b/tests/cleardiv.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# cleardiv.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2739 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert(-1) +undivert +EOF + +cat <<\EOF >ok +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/cleardiv.2.test b/tests/cleardiv.2.test new file mode 100755 index 00000000..1f5df3ac --- /dev/null +++ b/tests/cleardiv.2.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# cleardiv.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2754 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/define.1.test b/tests/define.1.test new file mode 100755 index 00000000..cffdbacb --- /dev/null +++ b/tests/define.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# define.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 988 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +foo +EOF + +cat <<\EOF >ok + +Hello world. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/define.2.test b/tests/define.2.test new file mode 100755 index 00000000..e4df34eb --- /dev/null +++ b/tests/define.2.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# define.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1008 + +. ${srcdir}/defs + +cat <<\EOF >in +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(eval(10+7)) +EOF + +cat <<\EOF >ok + + + + +array element no. 4 +array element no. 17 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/defn.1.test b/tests/defn.1.test new file mode 100755 index 00000000..bf54769c --- /dev/null +++ b/tests/defn.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# defn.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1231 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`zap', defn(`undefine')) +zap(`undefine') +undefine(`zap') +EOF + +cat <<\EOF >ok + + +undefine(zap) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/defn.2.test b/tests/defn.2.test new file mode 100755 index 00000000..33ea48bd --- /dev/null +++ b/tests/defn.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# defn.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1251 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`string', `The macro dnl is very useful +') +string +defn(`string') +EOF + +cat <<\EOF >ok + +The macro +The macro dnl is very useful + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/defs b/tests/defs new file mode 100644 index 00000000..cf97e3b3 --- /dev/null +++ b/tests/defs @@ -0,0 +1,54 @@ +# -*- ksh -*- +# Defines for GNU m4 testing environment. +# Erick Branderhorst <Erick.Branderhorst@asml.nl> + +# Ensure $srcdir set correctly. +test -f ${srcdir}/defs || { + echo "defs: installation error" 1>&2 + exit 1 +} + +# If srcdir is relative, we need to modify it. +case "$srcdir" in + /*) + ;; + + *) + srcdir="../$srcdir" + ;; +esac + +rm -rf testSubDir > /dev/null 2>&1 +mkdir testSubDir +cd testSubDir + +# Build appropriate environment in test directory. Eg create +# configure.in, touch all necessary files, etc. + +# nothing yet + +# See how redirections should work. User can set VERBOSE to see all +# output. +test -z "$VERBOSE" && { + exec > /dev/null 2>&1 +} + +# User can set MAKE to choose which make to use. Must use GNU make. +test -z "$MAKE" && MAKE=make + +echo "=== Running test $0" + +# See how GNU m4 should be run. No options as default. +test -z "$M4" && M4=../../src/m4 + +# See how cmp should be run. +test -z "$CMP" && CMP=cmp + +# Setting nls related vars. Override them in the test when needed. +LANGUAGE=C +export LANGUAGE +LC_ALL=C +export LC_ALL +LANG=C +export LANG + diff --git a/tests/divert.1.test b/tests/divert.1.test new file mode 100755 index 00000000..3a2a82ac --- /dev/null +++ b/tests/divert.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# divert.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2581 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/divert.2.test b/tests/divert.2.test new file mode 100755 index 00000000..2f22d845 --- /dev/null +++ b/tests/divert.2.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# divert.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2601 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/divnum.1.test b/tests/divnum.1.test new file mode 100755 index 00000000..c1c2638d --- /dev/null +++ b/tests/divnum.1.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# divnum.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2708 + +. ${srcdir}/defs + +cat <<\EOF >in +Initial divnum +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +EOF + +cat <<\EOF >ok +Initial 0 + + +Diversion one: 1 + +Diversion two: 2 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/dnl.1.test b/tests/dnl.1.test new file mode 100755 index 00000000..ecfa0077 --- /dev/null +++ b/tests/dnl.1.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# dnl.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1858 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. +foo +EOF + +cat <<\EOF >ok +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/dumpdef.1.test b/tests/dumpdef.1.test new file mode 100755 index 00000000..45a21ddd --- /dev/null +++ b/tests/dumpdef.1.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# dumpdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1661 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +dumpdef(`foo') +dumpdef(`define') +EOF + +cat <<\EOF >ok + + + +EOF + +cat <<\EOF >okerr +foo: `Hello world.' +define: <define> +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/errprint.1.test b/tests/errprint.1.test new file mode 100755 index 00000000..b1d6145c --- /dev/null +++ b/tests/errprint.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# errprint.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3427 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`Illegal arguments to forloop +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +Illegal arguments to forloop +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/errprint.2.test b/tests/errprint.2.test new file mode 100755 index 00000000..8f44ca0a --- /dev/null +++ b/tests/errprint.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# errprint.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3452 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`m4:'__file__:__line__: `Input error +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4:in:1: Input error +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/esyscmd.1.test b/tests/esyscmd.1.test new file mode 100755 index 00000000..b32c6ced --- /dev/null +++ b/tests/esyscmd.1.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# esyscmd.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3316 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`vice', `esyscmd(grep Vice ../Makefile)') +vice +EOF + +cat <<\EOF >ok + +# Ty Coon, President of Vice + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/eval.1.test b/tests/eval.1.test new file mode 100755 index 00000000..ef9a3ca3 --- /dev/null +++ b/tests/eval.1.test @@ -0,0 +1,38 @@ +#!/bin/sh + +# eval.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3200 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(-3 * 5) +eval(index(`Hello world', `llo') >= 0) +define(`square', `eval(($1)**2)') +square(9) +square(square(5)+1) +define(`foo', `666') +eval(`foo'/6) +eval(foo/6) +EOF + +cat <<\EOF >ok +-15 +1 + +81 +676 + + +111 +EOF + +cat <<\EOF >okerr +in:7: m4: Bad expression in eval: foo/6 +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/eval.2.test b/tests/eval.2.test new file mode 100755 index 00000000..374b7039 --- /dev/null +++ b/tests/eval.2.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# eval.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3231 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(666, 10) +eval(666, 11) +eval(666, 6) +eval(666, 6, 10) +eval(-666, 6, 10) +EOF + +cat <<\EOF >ok +666 +556 +3030 +0000003030 +-000003030 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/foo b/tests/foo new file mode 100644 index 00000000..5716ca59 --- /dev/null +++ b/tests/foo @@ -0,0 +1 @@ +bar diff --git a/tests/format.1.test b/tests/format.1.test new file mode 100755 index 00000000..0434ff23 --- /dev/null +++ b/tests/format.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# format.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3036 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `The brown fox jumped over the lazy dog') +format(`The string "%s" is %d characters long', foo, len(foo)) +EOF + +cat <<\EOF >ok + +The string "The brown fox jumped over the lazy dog" is 38 characters long +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/argument.1.test b/tests/generated-tests/argument.1.test new file mode 100755 index 00000000..25b1d819 --- /dev/null +++ b/tests/generated-tests/argument.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/argument.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1030 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +exch(arg1, arg2) +EOF + +cat <<\EOF >ok + +arg2, arg1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/argument.2.test b/tests/generated-tests/argument.2.test new file mode 100755 index 00000000..c077ec2a --- /dev/null +++ b/tests/generated-tests/argument.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/argument.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1040 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +define(exch(``expansion text'', ``macro'')) +macro +EOF + +cat <<\EOF >ok + + +expansion text +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/argument.3.test b/tests/generated-tests/argument.3.test new file mode 100755 index 00000000..2a514172 --- /dev/null +++ b/tests/generated-tests/argument.3.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/argument.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1060 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', ``Macro name: $0'') +test +EOF + +cat <<\EOF >ok + +Macro name: test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/argument.4.test b/tests/generated-tests/argument.4.test new file mode 100755 index 00000000..2459f966 --- /dev/null +++ b/tests/generated-tests/argument.4.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/argument.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1070 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `This is macro `foo'.') +foo +EOF + +cat <<\EOF >ok + +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changeco.1.test b/tests/generated-tests/changeco.1.test new file mode 100755 index 00000000..cc95cdbc --- /dev/null +++ b/tests/generated-tests/changeco.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/changeco.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1953 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +# A normal comment +changecom(`/*', `*/') +# Not a comment anymore +But: /* this is a comment now */ while this is not a comment +EOF + +cat <<\EOF >ok + +# A normal comment + +# Not a COMMENT anymore +But: /* this is a comment now */ while this is not a COMMENT +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changeco.2.test b/tests/generated-tests/changeco.2.test new file mode 100755 index 00000000..4e4fc01b --- /dev/null +++ b/tests/generated-tests/changeco.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/changeco.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1974 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +changecom +# Not a comment anymore +EOF + +cat <<\EOF >ok + + +# Not a COMMENT anymore +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changequ.1.test b/tests/generated-tests/changequ.1.test new file mode 100755 index 00000000..b66db9cf --- /dev/null +++ b/tests/generated-tests/changequ.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/changequ.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1889 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([, ]) +define([foo], [Macro [foo].]) +foo +EOF + +cat <<\EOF >ok + + +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changequ.2.test b/tests/generated-tests/changequ.2.test new file mode 100755 index 00000000..6ae416a9 --- /dev/null +++ b/tests/generated-tests/changequ.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/changequ.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1901 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([[, ]]) +define([[foo]], [[Macro [[[foo]]].]]) +foo +EOF + +cat <<\EOF >ok + + +Macro [foo]. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changequ.3.test b/tests/generated-tests/changequ.3.test new file mode 100755 index 00000000..baed4cdb --- /dev/null +++ b/tests/generated-tests/changequ.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/changequ.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1913 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `FOO'.') +changequote(, ) +foo +`foo' +EOF + +cat <<\EOF >ok + + +Macro `FOO'. +`Macro `FOO'.' +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.1.test b/tests/generated-tests/changesy.1.test new file mode 100755 index 00000000..7e925d10 --- /dev/null +++ b/tests/generated-tests/changesy.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/changesy.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2119 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test.1', `TEST ONE') +__file__ +changesyntax(`O_', `W.') +__file__ +test.1 +EOF + +cat <<\EOF >ok + +in + +__file__ +TEST ONE +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.2.test b/tests/generated-tests/changesy.2.test new file mode 100755 index 00000000..af4aa27c --- /dev/null +++ b/tests/generated-tests/changesy.2.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/changesy.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2135 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$#') +test(a, b, c) +changesyntax(`(<', `,|', `)>', `O(,)') +test(a, b, c) +test<a|b|c> +EOF + +cat <<\EOF >ok + +3 + +0(a, b, c) +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.3.test b/tests/generated-tests/changesy.3.test new file mode 100755 index 00000000..6229d772 --- /dev/null +++ b/tests/generated-tests/changesy.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/changesy.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2152 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$1$2$3') +test(a, b, c) +changesyntax(`O ') +test(a, b, c) +EOF + +cat <<\EOF >ok + +abc + +a b c +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.4.test b/tests/generated-tests/changesy.4.test new file mode 100755 index 00000000..64572a97 --- /dev/null +++ b/tests/generated-tests/changesy.4.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/changesy.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2171 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`@', `TEST') +@ +changesyntax(`A@') +@ +EOF + +cat <<\EOF >ok + +@ + +TEST +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.5.test b/tests/generated-tests/changesy.5.test new file mode 100755 index 00000000..83608521 --- /dev/null +++ b/tests/generated-tests/changesy.5.test @@ -0,0 +1,31 @@ +#!/bin/sh + +# generated-tests/changesy.5.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2195 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `TEST') +changesyntax(`L<', `R>') +<test> +`test> +changequote(<[>, `]') +<test> +[test] +EOF + +cat <<\EOF >ok + + +test +test + +<TEST> +test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.6.test b/tests/generated-tests/changesy.6.test new file mode 100755 index 00000000..14066fec --- /dev/null +++ b/tests/generated-tests/changesy.6.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/changesy.6.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2217 + +. ${srcdir}/defs + +cat <<\EOF >in +changesyntax(`({<', `)}>', `,;:', `O(,)') +eval{2**4-1; 2 : 8> +EOF + +cat <<\EOF >ok + +00001111 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.7.test b/tests/generated-tests/changesy.7.test new file mode 100755 index 00000000..9e70c202 --- /dev/null +++ b/tests/generated-tests/changesy.7.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# generated-tests/changesy.7.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2228 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `==$1==') +changequote(`<<', `>>') +changesyntax(<<L[>>, <<R]>>) +test(<<testing]>>) +test([testing>>]) +test([<<testing>>]) +EOF + +cat <<\EOF >ok + + + +==testing]== +==testing>>== +==testing== +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/changesy.8.test b/tests/generated-tests/changesy.8.test new file mode 100755 index 00000000..a087f85a --- /dev/null +++ b/tests/generated-tests/changesy.8.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# generated-tests/changesy.8.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2282 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `==$1==') +changequote(`<<', `>>') +changesyntax(<<L[>>, <<R]>>) +test(<<testing]>>) +test([testing>>]) +test([<<testing>>]) +EOF + +cat <<\EOF >ok + + + +==testing]== +==testing>>== +==testing== +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/cleardiv.1.test b/tests/generated-tests/cleardiv.1.test new file mode 100755 index 00000000..c7dc0655 --- /dev/null +++ b/tests/generated-tests/cleardiv.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/cleardiv.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2732 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert(-1) +undivert +EOF + +cat <<\EOF >ok +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/cleardiv.2.test b/tests/generated-tests/cleardiv.2.test new file mode 100755 index 00000000..23324698 --- /dev/null +++ b/tests/generated-tests/cleardiv.2.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# generated-tests/cleardiv.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2747 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/define.1.test b/tests/generated-tests/define.1.test new file mode 100755 index 00000000..eefece84 --- /dev/null +++ b/tests/generated-tests/define.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/define.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 981 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +foo +EOF + +cat <<\EOF >ok + +Hello world. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/define.2.test b/tests/generated-tests/define.2.test new file mode 100755 index 00000000..1b18fe06 --- /dev/null +++ b/tests/generated-tests/define.2.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# generated-tests/define.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1001 + +. ${srcdir}/defs + +cat <<\EOF >in +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(eval(10+7)) +EOF + +cat <<\EOF >ok + + + + +array element no. 4 +array element no. 17 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/defn.1.test b/tests/generated-tests/defn.1.test new file mode 100755 index 00000000..1922b358 --- /dev/null +++ b/tests/generated-tests/defn.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/defn.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1224 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`zap', defn(`undefine')) +zap(`undefine') +undefine(`zap') +EOF + +cat <<\EOF >ok + + +undefine(zap) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/defn.2.test b/tests/generated-tests/defn.2.test new file mode 100755 index 00000000..0cac7363 --- /dev/null +++ b/tests/generated-tests/defn.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/defn.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1244 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`string', `The macro dnl is very useful +') +string +defn(`string') +EOF + +cat <<\EOF >ok + +The macro +The macro dnl is very useful + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/divert.1.test b/tests/generated-tests/divert.1.test new file mode 100755 index 00000000..83d5d9a2 --- /dev/null +++ b/tests/generated-tests/divert.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/divert.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2574 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/divert.2.test b/tests/generated-tests/divert.2.test new file mode 100755 index 00000000..f5cd9f8c --- /dev/null +++ b/tests/generated-tests/divert.2.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# generated-tests/divert.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2594 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/divnum.1.test b/tests/generated-tests/divnum.1.test new file mode 100755 index 00000000..ddcb689e --- /dev/null +++ b/tests/generated-tests/divnum.1.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# generated-tests/divnum.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2701 + +. ${srcdir}/defs + +cat <<\EOF >in +Initial divnum +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +EOF + +cat <<\EOF >ok +Initial 0 + + +Diversion one: 1 + +Diversion two: 2 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/dnl.1.test b/tests/generated-tests/dnl.1.test new file mode 100755 index 00000000..b80528d5 --- /dev/null +++ b/tests/generated-tests/dnl.1.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# generated-tests/dnl.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1851 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. +foo +EOF + +cat <<\EOF >ok +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/dumpdef.1.test b/tests/generated-tests/dumpdef.1.test new file mode 100755 index 00000000..677a5974 --- /dev/null +++ b/tests/generated-tests/dumpdef.1.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# generated-tests/dumpdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1654 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +dumpdef(`foo') +dumpdef(`define') +EOF + +cat <<\EOF >ok + + + +EOF + +cat <<\EOF >okerr +foo: `Hello world.' +define: <define> +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/errprint.1.test b/tests/generated-tests/errprint.1.test new file mode 100755 index 00000000..d89d95b8 --- /dev/null +++ b/tests/generated-tests/errprint.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/errprint.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3420 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`Illegal arguments to forloop +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +Illegal arguments to forloop +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/errprint.2.test b/tests/generated-tests/errprint.2.test new file mode 100755 index 00000000..e7e6946b --- /dev/null +++ b/tests/generated-tests/errprint.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/errprint.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3445 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`m4:'__file__:__line__: `Input error +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4:in:1: Input error +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/esyscmd.1.test b/tests/generated-tests/esyscmd.1.test new file mode 100755 index 00000000..0f4135d5 --- /dev/null +++ b/tests/generated-tests/esyscmd.1.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# generated-tests/esyscmd.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3309 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`vice', `esyscmd(grep Vice ../Makefile)') +vice +EOF + +cat <<\EOF >ok + +# Ty Coon, President of Vice + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/eval.1.test b/tests/generated-tests/eval.1.test new file mode 100755 index 00000000..73fd306b --- /dev/null +++ b/tests/generated-tests/eval.1.test @@ -0,0 +1,38 @@ +#!/bin/sh + +# generated-tests/eval.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3193 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(-3 * 5) +eval(index(`Hello world', `llo') >= 0) +define(`square', `eval(($1)**2)') +square(9) +square(square(5)+1) +define(`foo', `666') +eval(`foo'/6) +eval(foo/6) +EOF + +cat <<\EOF >ok +-15 +1 + +81 +676 + + +111 +EOF + +cat <<\EOF >okerr +in:7: m4: Bad expression in eval: foo/6 +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/eval.2.test b/tests/generated-tests/eval.2.test new file mode 100755 index 00000000..443672d1 --- /dev/null +++ b/tests/generated-tests/eval.2.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/eval.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3224 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(666, 10) +eval(666, 11) +eval(666, 6) +eval(666, 6, 10) +eval(-666, 6, 10) +EOF + +cat <<\EOF >ok +666 +556 +3030 +0000003030 +-000003030 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/format.1.test b/tests/generated-tests/format.1.test new file mode 100755 index 00000000..52fc5029 --- /dev/null +++ b/tests/generated-tests/format.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/format.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3029 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `The brown fox jumped over the lazy dog') +format(`The string "%s" is %d characters long', foo, len(foo)) +EOF + +cat <<\EOF >ok + +The string "The brown fox jumped over the lazy dog" is 38 characters long +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/ifdef.1.test b/tests/generated-tests/ifdef.1.test new file mode 100755 index 00000000..559745fa --- /dev/null +++ b/tests/generated-tests/ifdef.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/ifdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1434 + +. ${srcdir}/defs + +cat <<\EOF >in +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +define(`foo', `') +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +EOF + +cat <<\EOF >ok +foo is not defined + +foo is defined +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/ifelse.1.test b/tests/generated-tests/ifelse.1.test new file mode 100755 index 00000000..82b2770c --- /dev/null +++ b/tests/generated-tests/ifelse.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/ifelse.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1472 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(`foo', `bar', `true') +ifelse(`foo', `foo', `true') +ifelse(`foo', `bar', `true', `false') +ifelse(`foo', `foo', `true', `false') +EOF + +cat <<\EOF >ok + +true +false +true +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/ifelse.2.test b/tests/generated-tests/ifelse.2.test new file mode 100755 index 00000000..9181abd0 --- /dev/null +++ b/tests/generated-tests/ifelse.2.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# generated-tests/ifelse.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1491 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +EOF + +cat <<\EOF >ok +seventh +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/include.1.test b/tests/generated-tests/include.1.test new file mode 100755 index 00000000..cd8274bd --- /dev/null +++ b/tests/generated-tests/include.1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# generated-tests/include.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2448 + +. ${srcdir}/defs + +cat <<\EOF >in +include(`no-such-file') +sinclude(`no-such-file') +EOF + +cat <<\EOF >ok + + +EOF + +cat <<\EOF >okerr +in:1: m4: Cannot open no-such-file: No such file or directory +EOF + +M4PATH=$srcdir $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/include.2.test b/tests/generated-tests/include.2.test new file mode 100755 index 00000000..94446fd7 --- /dev/null +++ b/tests/generated-tests/include.2.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# generated-tests/include.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2468 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `FOO') +include(`incl.m4') +EOF + +cat <<\EOF >ok + +Include file start +FOO +Include file end + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/include.3.test b/tests/generated-tests/include.3.test new file mode 100755 index 00000000..1cb768d9 --- /dev/null +++ b/tests/generated-tests/include.3.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# generated-tests/include.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2483 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', include(`incl.m4')) +This is `bar': >>>bar<<< +EOF + +cat <<\EOF >ok + +This is bar: >>>Include file start +foo +Include file end +<<< +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/incr.1.test b/tests/generated-tests/incr.1.test new file mode 100755 index 00000000..f07ddf7c --- /dev/null +++ b/tests/generated-tests/incr.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/incr.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3099 + +. ${srcdir}/defs + +cat <<\EOF >in +incr(4) +decr(7) +EOF + +cat <<\EOF >ok +5 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/index.1.test b/tests/generated-tests/index.1.test new file mode 100755 index 00000000..11768455 --- /dev/null +++ b/tests/generated-tests/index.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/index.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2815 + +. ${srcdir}/defs + +cat <<\EOF >in +index(`gnus, gnats, and armadillos', `nat') +index(`gnus, gnats, and armadillos', `dag') +EOF + +cat <<\EOF >ok +7 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/indir.1.test b/tests/generated-tests/indir.1.test new file mode 100755 index 00000000..c37cc49b --- /dev/null +++ b/tests/generated-tests/indir.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/indir.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1363 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`$$internal$macro', `Internal macro (name `$0')') +$$internal$macro +indir(`$$internal$macro') +EOF + +cat <<\EOF >ok + +$$internal$macro +Internal macro (name $$internal$macro) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/len.1.test b/tests/generated-tests/len.1.test new file mode 100755 index 00000000..dac41506 --- /dev/null +++ b/tests/generated-tests/len.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/len.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2789 + +. ${srcdir}/defs + +cat <<\EOF >in +len() +len(`abcdef') +EOF + +cat <<\EOF >ok +0 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/loops.1.test b/tests/generated-tests/loops.1.test new file mode 100755 index 00000000..880f95d9 --- /dev/null +++ b/tests/generated-tests/loops.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/loops.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1528 + +. ${srcdir}/defs + +cat <<\EOF >in +shift +shift(bar) +shift(foo, bar, baz) +EOF + +cat <<\EOF >ok + + +bar,baz +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/loops.2.test b/tests/generated-tests/loops.2.test new file mode 100755 index 00000000..7b537032 --- /dev/null +++ b/tests/generated-tests/loops.2.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# generated-tests/loops.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1540 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', + `reverse(shift($@)), `$1'')') +reverse +reverse(foo) +reverse(foo, bar, gnats, and gnus) +EOF + +cat <<\EOF >ok + + +foo +and gnus, gnats, bar, foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/m4exit.1.test b/tests/generated-tests/m4exit.1.test new file mode 100755 index 00000000..78aba0fd --- /dev/null +++ b/tests/generated-tests/m4exit.1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# generated-tests/m4exit.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3468 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +fatal_error(`This is a BAD one, buster') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4: in: 3: fatal error: This is a BAD one, buster +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/m4wrap.1.test b/tests/generated-tests/m4wrap.1.test new file mode 100755 index 00000000..0f9419dd --- /dev/null +++ b/tests/generated-tests/m4wrap.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/m4wrap.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2389 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleanup', `This is the `cleanup' actions. +') +m4wrap(`cleanup') +This is the first and last normal input line. +EOF + +cat <<\EOF >ok + + +This is the first and last normal input line. +This is the cleanup actions. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/patsubst.1.test b/tests/generated-tests/patsubst.1.test new file mode 100755 index 00000000..4f04ac25 --- /dev/null +++ b/tests/generated-tests/patsubst.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/patsubst.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2977 + +. ${srcdir}/defs + +cat <<\EOF >in +patsubst(`GNUs not Unix', `^', `OBS: ') +patsubst(`GNUs not Unix', `\<', `OBS: ') +patsubst(`GNUs not Unix', `\w*', `(\&)') +patsubst(`GNUs not Unix', `\w+', `(\&)') +patsubst(`GNUs not Unix', `[A-Z][a-z]+') +EOF + +cat <<\EOF >ok +OBS: GNUs not Unix +OBS: GNUs OBS: not OBS: Unix +(GNUs)() (not)() (Unix) +(GNUs) (not) (Unix) +GN not +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/patsubst.2.test b/tests/generated-tests/patsubst.2.test new file mode 100755 index 00000000..d651a184 --- /dev/null +++ b/tests/generated-tests/patsubst.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/patsubst.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2994 + +. ${srcdir}/defs + +cat <<\EOF >in +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') +EOF + +cat <<\EOF >ok +Gnus Not Unix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pseudoar.1.test b/tests/generated-tests/pseudoar.1.test new file mode 100755 index 00000000..de5cabc2 --- /dev/null +++ b/tests/generated-tests/pseudoar.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/pseudoar.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1094 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`nargs', `$#') +nargs +nargs() +nargs(arg1, arg2, arg3) +EOF + +cat <<\EOF >ok + +0 +1 +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pseudoar.2.test b/tests/generated-tests/pseudoar.2.test new file mode 100755 index 00000000..b8418771 --- /dev/null +++ b/tests/generated-tests/pseudoar.2.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/pseudoar.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1108 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$*') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pseudoar.3.test b/tests/generated-tests/pseudoar.3.test new file mode 100755 index 00000000..26f6ebb3 --- /dev/null +++ b/tests/generated-tests/pseudoar.3.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/pseudoar.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1119 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$@') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pseudoar.4.test b/tests/generated-tests/pseudoar.4.test new file mode 100755 index 00000000..8622426f --- /dev/null +++ b/tests/generated-tests/pseudoar.4.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/pseudoar.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1129 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo1', `$*') +define(`echo2', `$@') +define(`foo', `This is macro `foo'.') +echo1(foo) +echo2(foo) +EOF + +cat <<\EOF >ok + + + +This is macro This is macro foo.. +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pseudoar.5.test b/tests/generated-tests/pseudoar.5.test new file mode 100755 index 00000000..1ed05635 --- /dev/null +++ b/tests/generated-tests/pseudoar.5.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/pseudoar.5.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1149 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `$$$ hello $$$') +foo +EOF + +cat <<\EOF >ok + +$$$ hello $$$ +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pushdef.1.test b/tests/generated-tests/pushdef.1.test new file mode 100755 index 00000000..09d5f945 --- /dev/null +++ b/tests/generated-tests/pushdef.1.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# generated-tests/pushdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1288 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +popdef(`foo') +foo +popdef(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Expansion one. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/pushdef.2.test b/tests/generated-tests/pushdef.2.test new file mode 100755 index 00000000..091c27e1 --- /dev/null +++ b/tests/generated-tests/pushdef.2.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# generated-tests/pushdef.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1312 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +define(`foo', `Second expansion two.') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Second expansion two. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/regexp.1.test b/tests/generated-tests/regexp.1.test new file mode 100755 index 00000000..df471907 --- /dev/null +++ b/tests/generated-tests/regexp.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/regexp.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2847 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\<[a-z]\w+') +regexp(`GNUs not Unix', `\<Q\w*') +EOF + +cat <<\EOF >ok +5 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/regexp.2.test b/tests/generated-tests/regexp.2.test new file mode 100755 index 00000000..22cb99c6 --- /dev/null +++ b/tests/generated-tests/regexp.2.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# generated-tests/regexp.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2859 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +EOF + +cat <<\EOF >ok +*** Unix *** nix *** +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/substr.1.test b/tests/generated-tests/substr.1.test new file mode 100755 index 00000000..4ad45539 --- /dev/null +++ b/tests/generated-tests/substr.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# generated-tests/substr.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2885 + +. ${srcdir}/defs + +cat <<\EOF >in +substr(`gnus, gnats, and armadillos', 6) +substr(`gnus, gnats, and armadillos', 6, 5) +EOF + +cat <<\EOF >ok +gnats, and armadillos +gnats +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/symbols.1.test b/tests/generated-tests/symbols.1.test new file mode 100755 index 00000000..4414ee13 --- /dev/null +++ b/tests/generated-tests/symbols.1.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# generated-tests/symbols.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1442 + +. ${srcdir}/defs + +cat <<\EOF >in +symbols(`ifndef', `ifdef', `define', `undef') +EOF + +cat <<\EOF >ok +define,ifdef +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/sysval.1.test b/tests/generated-tests/sysval.1.test new file mode 100755 index 00000000..5cb177f1 --- /dev/null +++ b/tests/generated-tests/sysval.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/sysval.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3340 + +. ${srcdir}/defs + +cat <<\EOF >in +syscmd(`false') +ifelse(sysval, 0, zero, nonzero) +syscmd(`true') +sysval +EOF + +cat <<\EOF >ok + +nonzero + +0 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/trace.1.test b/tests/generated-tests/trace.1.test new file mode 100755 index 00000000..9acf3a12 --- /dev/null +++ b/tests/generated-tests/trace.1.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# generated-tests/trace.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1699 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello World.') +define(`echo', `$@') +traceon(`foo', `echo') +foo +echo(gnus, and gnats) +EOF + +cat <<\EOF >ok + + + +Hello World. +gnus,and gnats +EOF + +cat <<\EOF >okerr +m4trace: -1- foo -> `Hello World.' +m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/generated-tests/translit.1.test b/tests/generated-tests/translit.1.test new file mode 100755 index 00000000..da6710c7 --- /dev/null +++ b/tests/generated-tests/translit.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# generated-tests/translit.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2926 + +. ${srcdir}/defs + +cat <<\EOF >in +translit(`GNUs not Unix', `A-Z') +translit(`GNUs not Unix', `a-z', `A-Z') +translit(`GNUs not Unix', `A-Z', `z-a') +EOF + +cat <<\EOF >ok +s not nix +GNUS NOT UNIX +tmfs not fnix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/undefine.1.test b/tests/generated-tests/undefine.1.test new file mode 100755 index 00000000..bac0cd29 --- /dev/null +++ b/tests/generated-tests/undefine.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/undefine.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1180 + +. ${srcdir}/defs + +cat <<\EOF >in +foo +define(`foo', `expansion text') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok +foo + +expansion text + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/undivert.1.test b/tests/generated-tests/undivert.1.test new file mode 100755 index 00000000..18c904ba --- /dev/null +++ b/tests/generated-tests/undivert.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# generated-tests/undivert.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2625 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +undivert(1) +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/undivert.2.test b/tests/generated-tests/undivert.2.test new file mode 100755 index 00000000..44485600 --- /dev/null +++ b/tests/generated-tests/undivert.2.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# generated-tests/undivert.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2649 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted first. +divert(0)undivert(1)dnl +undivert(1) +divert(1) +This text is also diverted but not appended. +divert(0)undivert(1)dnl +EOF + +cat <<\EOF >ok + +This text is diverted first. + + +This text is also diverted but not appended. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/generated-tests/undivert.3.test b/tests/generated-tests/undivert.3.test new file mode 100755 index 00000000..a85a9d0c --- /dev/null +++ b/tests/generated-tests/undivert.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# generated-tests/undivert.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2675 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', `BAR') +undivert(`foo') +include(`foo') +EOF + +cat <<\EOF >ok + +bar + +BAR + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.1.m4 b/tests/gentest/argument.1.m4 new file mode 100755 index 00000000..04909dc9 --- /dev/null +++ b/tests/gentest/argument.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/argument.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1036 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +exch(arg1, arg2) +EOF + +cat <<\EOF >ok + +arg2, arg1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.1.test b/tests/gentest/argument.1.test new file mode 100755 index 00000000..e8f48197 --- /dev/null +++ b/tests/gentest/argument.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/argument.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1036 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +exch(arg1, arg2) +EOF + +cat <<\EOF >ok + +arg2, arg1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.2.m4 b/tests/gentest/argument.2.m4 new file mode 100755 index 00000000..59814143 --- /dev/null +++ b/tests/gentest/argument.2.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/argument.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1046 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +define(exch(``expansion text'', ``macro'')) +macro +EOF + +cat <<\EOF >ok + + +expansion text +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.2.test b/tests/gentest/argument.2.test new file mode 100755 index 00000000..3e2149b5 --- /dev/null +++ b/tests/gentest/argument.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/argument.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1046 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`exch', `$2, $1') +define(exch(``expansion text'', ``macro'')) +macro +EOF + +cat <<\EOF >ok + + +expansion text +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.3.m4 b/tests/gentest/argument.3.m4 new file mode 100755 index 00000000..3dae6ca9 --- /dev/null +++ b/tests/gentest/argument.3.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/argument.3.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1066 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', ``Macro name: $0'') +test +EOF + +cat <<\EOF >ok + +Macro name: test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.3.test b/tests/gentest/argument.3.test new file mode 100755 index 00000000..5ffdafd4 --- /dev/null +++ b/tests/gentest/argument.3.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/argument.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1066 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', ``Macro name: $0'') +test +EOF + +cat <<\EOF >ok + +Macro name: test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.4.m4 b/tests/gentest/argument.4.m4 new file mode 100755 index 00000000..39389759 --- /dev/null +++ b/tests/gentest/argument.4.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/argument.4.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1076 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `This is macro `foo'.') +foo +EOF + +cat <<\EOF >ok + +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/argument.4.test b/tests/gentest/argument.4.test new file mode 100755 index 00000000..b28f5638 --- /dev/null +++ b/tests/gentest/argument.4.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/argument.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1076 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `This is macro `foo'.') +foo +EOF + +cat <<\EOF >ok + +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changeco.1.m4 b/tests/gentest/changeco.1.m4 new file mode 100755 index 00000000..533b931b --- /dev/null +++ b/tests/gentest/changeco.1.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/changeco.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1959 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +# A normal comment +changecom(`/*', `*/') +# Not a comment anymore +But: /* this is a comment now */ while this is not a comment +EOF + +cat <<\EOF >ok + +# A normal comment + +# Not a COMMENT anymore +But: /* this is a comment now */ while this is not a COMMENT +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changeco.1.test b/tests/gentest/changeco.1.test new file mode 100755 index 00000000..08ad873d --- /dev/null +++ b/tests/gentest/changeco.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/changeco.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1959 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +# A normal comment +changecom(`/*', `*/') +# Not a comment anymore +But: /* this is a comment now */ while this is not a comment +EOF + +cat <<\EOF >ok + +# A normal comment + +# Not a COMMENT anymore +But: /* this is a comment now */ while this is not a COMMENT +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changeco.2.m4 b/tests/gentest/changeco.2.m4 new file mode 100755 index 00000000..dfd0aa1d --- /dev/null +++ b/tests/gentest/changeco.2.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/changeco.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1980 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +changecom +# Not a comment anymore +EOF + +cat <<\EOF >ok + + +# Not a COMMENT anymore +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changeco.2.test b/tests/gentest/changeco.2.test new file mode 100755 index 00000000..c265d1f5 --- /dev/null +++ b/tests/gentest/changeco.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/changeco.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1980 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`comment', `COMMENT') +changecom +# Not a comment anymore +EOF + +cat <<\EOF >ok + + +# Not a COMMENT anymore +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changequ.1.m4 b/tests/gentest/changequ.1.m4 new file mode 100755 index 00000000..7022cec9 --- /dev/null +++ b/tests/gentest/changequ.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/changequ.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1895 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([, ]) +define([foo], [Macro [foo].]) +foo +EOF + +cat <<\EOF >ok + + +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changequ.1.test b/tests/gentest/changequ.1.test new file mode 100755 index 00000000..f0f64f69 --- /dev/null +++ b/tests/gentest/changequ.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/changequ.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1895 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([, ]) +define([foo], [Macro [foo].]) +foo +EOF + +cat <<\EOF >ok + + +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changequ.2.m4 b/tests/gentest/changequ.2.m4 new file mode 100755 index 00000000..5eba166b --- /dev/null +++ b/tests/gentest/changequ.2.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/changequ.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1907 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([[, ]]) +define([[foo]], [[Macro [[[foo]]].]]) +foo +EOF + +cat <<\EOF >ok + + +Macro [foo]. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changequ.2.test b/tests/gentest/changequ.2.test new file mode 100755 index 00000000..0ec4ad14 --- /dev/null +++ b/tests/gentest/changequ.2.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/changequ.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1907 + +. ${srcdir}/defs + +cat <<\EOF >in +changequote([[, ]]) +define([[foo]], [[Macro [[[foo]]].]]) +foo +EOF + +cat <<\EOF >ok + + +Macro [foo]. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changequ.3.m4 b/tests/gentest/changequ.3.m4 new file mode 100755 index 00000000..6174e994 --- /dev/null +++ b/tests/gentest/changequ.3.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/changequ.3.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1919 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `FOO'.') +changequote(, ) +foo +`foo' +EOF + +cat <<\EOF >ok + + +Macro `FOO'. +`Macro `FOO'.' +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changequ.3.test b/tests/gentest/changequ.3.test new file mode 100755 index 00000000..83a8544f --- /dev/null +++ b/tests/gentest/changequ.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/changequ.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1919 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `FOO'.') +changequote(, ) +foo +`foo' +EOF + +cat <<\EOF >ok + + +Macro `FOO'. +`Macro `FOO'.' +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.1.m4 b/tests/gentest/changesy.1.m4 new file mode 100755 index 00000000..c608a21f --- /dev/null +++ b/tests/gentest/changesy.1.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/changesy.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2125 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test.1', `TEST ONE') +__file__ +changesyntax(`O_', `W.') +__file__ +test.1 +EOF + +cat <<\EOF >ok + +in + +__file__ +TEST ONE +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.1.test b/tests/gentest/changesy.1.test new file mode 100755 index 00000000..344bf506 --- /dev/null +++ b/tests/gentest/changesy.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/changesy.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2125 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test.1', `TEST ONE') +__file__ +changesyntax(`O_', `W.') +__file__ +test.1 +EOF + +cat <<\EOF >ok + +in + +__file__ +TEST ONE +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.2.m4 b/tests/gentest/changesy.2.m4 new file mode 100755 index 00000000..55a99375 --- /dev/null +++ b/tests/gentest/changesy.2.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/changesy.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2141 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$#') +test(a, b, c) +changesyntax(`(<', `,|', `)>', `O(,)') +test(a, b, c) +test<a|b|c> +EOF + +cat <<\EOF >ok + +3 + +0(a, b, c) +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.2.test b/tests/gentest/changesy.2.test new file mode 100755 index 00000000..544a8753 --- /dev/null +++ b/tests/gentest/changesy.2.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/changesy.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2141 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$#') +test(a, b, c) +changesyntax(`(<', `,|', `)>', `O(,)') +test(a, b, c) +test<a|b|c> +EOF + +cat <<\EOF >ok + +3 + +0(a, b, c) +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.3.m4 b/tests/gentest/changesy.3.m4 new file mode 100755 index 00000000..8f86a03a --- /dev/null +++ b/tests/gentest/changesy.3.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/changesy.3.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2158 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$1$2$3') +test(a, b, c) +changesyntax(`O ') +test(a, b, c) +EOF + +cat <<\EOF >ok + +abc + +a b c +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.3.test b/tests/gentest/changesy.3.test new file mode 100755 index 00000000..79030e78 --- /dev/null +++ b/tests/gentest/changesy.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/changesy.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2158 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `$1$2$3') +test(a, b, c) +changesyntax(`O ') +test(a, b, c) +EOF + +cat <<\EOF >ok + +abc + +a b c +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.4.m4 b/tests/gentest/changesy.4.m4 new file mode 100755 index 00000000..9ee5b7d1 --- /dev/null +++ b/tests/gentest/changesy.4.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/changesy.4.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2177 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`@', `TEST') +@ +changesyntax(`A@') +@ +EOF + +cat <<\EOF >ok + +@ + +TEST +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.4.test b/tests/gentest/changesy.4.test new file mode 100755 index 00000000..7df01f9e --- /dev/null +++ b/tests/gentest/changesy.4.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/changesy.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2177 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`@', `TEST') +@ +changesyntax(`A@') +@ +EOF + +cat <<\EOF >ok + +@ + +TEST +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.5.m4 b/tests/gentest/changesy.5.m4 new file mode 100755 index 00000000..2035d2b9 --- /dev/null +++ b/tests/gentest/changesy.5.m4 @@ -0,0 +1,31 @@ +#!/bin/sh + +# gentest/changesy.5.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2201 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `TEST') +changesyntax(`L<', `R>') +<test> +`test> +changequote(<[>, `]') +<test> +[test] +EOF + +cat <<\EOF >ok + + +test +test + +<TEST> +test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.5.test b/tests/gentest/changesy.5.test new file mode 100755 index 00000000..25640e31 --- /dev/null +++ b/tests/gentest/changesy.5.test @@ -0,0 +1,31 @@ +#!/bin/sh + +# gentest/changesy.5.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2201 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `TEST') +changesyntax(`L<', `R>') +<test> +`test> +changequote(<[>, `]') +<test> +[test] +EOF + +cat <<\EOF >ok + + +test +test + +<TEST> +test +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.6.m4 b/tests/gentest/changesy.6.m4 new file mode 100755 index 00000000..88cac7a4 --- /dev/null +++ b/tests/gentest/changesy.6.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/changesy.6.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2223 + +. ${srcdir}/defs + +cat <<\EOF >in +changesyntax(`({<', `)}>', `,;:', `O(,)') +eval{2**4-1; 2 : 8> +EOF + +cat <<\EOF >ok + +00001111 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.6.test b/tests/gentest/changesy.6.test new file mode 100755 index 00000000..91cfc80a --- /dev/null +++ b/tests/gentest/changesy.6.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/changesy.6.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2223 + +. ${srcdir}/defs + +cat <<\EOF >in +changesyntax(`({<', `)}>', `,;:', `O(,)') +eval{2**4-1; 2 : 8> +EOF + +cat <<\EOF >ok + +00001111 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.7.m4 b/tests/gentest/changesy.7.m4 new file mode 100755 index 00000000..7a366945 --- /dev/null +++ b/tests/gentest/changesy.7.m4 @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/changesy.7.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2234 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `==$1==') +changequote(`<<', `>>') +changesyntax(<<L[>>, <<R]>>) +test(<<testing]>>) +test([testing>>]) +test([<<testing>>]) +EOF + +cat <<\EOF >ok + + + +==testing]== +==testing>>== +==<<testing>>== +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/changesy.7.test b/tests/gentest/changesy.7.test new file mode 100755 index 00000000..014c152f --- /dev/null +++ b/tests/gentest/changesy.7.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/changesy.7.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2234 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`test', `==$1==') +changequote(`<<', `>>') +changesyntax(<<L[>>, <<R]>>) +test(<<testing]>>) +test([testing>>]) +test([<<testing>>]) +EOF + +cat <<\EOF >ok + + + +==testing]== +==testing>>== +==testing== +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/cleardiv.1.m4 b/tests/gentest/cleardiv.1.m4 new file mode 100755 index 00000000..36cba76a --- /dev/null +++ b/tests/gentest/cleardiv.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/cleardiv.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2738 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert(-1) +undivert +EOF + +cat <<\EOF >ok +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/cleardiv.1.test b/tests/gentest/cleardiv.1.test new file mode 100755 index 00000000..d9883e43 --- /dev/null +++ b/tests/gentest/cleardiv.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/cleardiv.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2738 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert(-1) +undivert +EOF + +cat <<\EOF >ok +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/cleardiv.2.m4 b/tests/gentest/cleardiv.2.m4 new file mode 100755 index 00000000..e44667a9 --- /dev/null +++ b/tests/gentest/cleardiv.2.m4 @@ -0,0 +1,20 @@ +#!/bin/sh + +# gentest/cleardiv.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2753 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/cleardiv.2.test b/tests/gentest/cleardiv.2.test new file mode 100755 index 00000000..7e78d8a4 --- /dev/null +++ b/tests/gentest/cleardiv.2.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# gentest/cleardiv.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2753 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleardivert', +`pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/define.1.m4 b/tests/gentest/define.1.m4 new file mode 100755 index 00000000..17f30775 --- /dev/null +++ b/tests/gentest/define.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/define.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 987 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +foo +EOF + +cat <<\EOF >ok + +Hello world. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/define.1.test b/tests/gentest/define.1.test new file mode 100755 index 00000000..fb364668 --- /dev/null +++ b/tests/gentest/define.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/define.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 987 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +foo +EOF + +cat <<\EOF >ok + +Hello world. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/define.2.m4 b/tests/gentest/define.2.m4 new file mode 100755 index 00000000..62e2ea0e --- /dev/null +++ b/tests/gentest/define.2.m4 @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/define.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1007 + +. ${srcdir}/defs + +cat <<\EOF >in +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(eval(10+7)) +EOF + +cat <<\EOF >ok + + + + +array element no. 4 +array element no. 17 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/define.2.test b/tests/gentest/define.2.test new file mode 100755 index 00000000..028642c3 --- /dev/null +++ b/tests/gentest/define.2.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/define.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1007 + +. ${srcdir}/defs + +cat <<\EOF >in +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(eval(10+7)) +EOF + +cat <<\EOF >ok + + + + +array element no. 4 +array element no. 17 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/defn.1.m4 b/tests/gentest/defn.1.m4 new file mode 100755 index 00000000..c3f06939 --- /dev/null +++ b/tests/gentest/defn.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/defn.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1230 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`zap', defn(`undefine')) +zap(`undefine') +undefine(`zap') +EOF + +cat <<\EOF >ok + + +undefine(zap) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/defn.1.test b/tests/gentest/defn.1.test new file mode 100755 index 00000000..868dc07e --- /dev/null +++ b/tests/gentest/defn.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/defn.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1230 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`zap', defn(`undefine')) +zap(`undefine') +undefine(`zap') +EOF + +cat <<\EOF >ok + + +undefine(zap) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/defn.2.m4 b/tests/gentest/defn.2.m4 new file mode 100755 index 00000000..0422980b --- /dev/null +++ b/tests/gentest/defn.2.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/defn.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1250 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`string', `The macro dnl is very useful +') +string +defn(`string') +EOF + +cat <<\EOF >ok + +The macro +The macro dnl is very useful + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/defn.2.test b/tests/gentest/defn.2.test new file mode 100755 index 00000000..df1925d4 --- /dev/null +++ b/tests/gentest/defn.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/defn.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1250 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`string', `The macro dnl is very useful +') +string +defn(`string') +EOF + +cat <<\EOF >ok + +The macro +The macro dnl is very useful + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/divert.1.m4 b/tests/gentest/divert.1.m4 new file mode 100755 index 00000000..acfc17d7 --- /dev/null +++ b/tests/gentest/divert.1.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/divert.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2580 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/divert.1.test b/tests/gentest/divert.1.test new file mode 100755 index 00000000..f675ba00 --- /dev/null +++ b/tests/gentest/divert.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/divert.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2580 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/divert.2.m4 b/tests/gentest/divert.2.m4 new file mode 100755 index 00000000..13075ff7 --- /dev/null +++ b/tests/gentest/divert.2.m4 @@ -0,0 +1,22 @@ +#!/bin/sh + +# gentest/divert.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2600 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/divert.2.test b/tests/gentest/divert.2.test new file mode 100755 index 00000000..87f745d7 --- /dev/null +++ b/tests/gentest/divert.2.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# gentest/divert.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2600 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(-1) +define(`foo', `Macro `foo'.') +define(`bar', `Macro `bar'.') +divert +EOF + +cat <<\EOF >ok + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/divnum.1.m4 b/tests/gentest/divnum.1.m4 new file mode 100755 index 00000000..4f49f918 --- /dev/null +++ b/tests/gentest/divnum.1.m4 @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/divnum.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2707 + +. ${srcdir}/defs + +cat <<\EOF >in +Initial divnum +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +EOF + +cat <<\EOF >ok +Initial 0 + + +Diversion one: 1 + +Diversion two: 2 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/divnum.1.test b/tests/gentest/divnum.1.test new file mode 100755 index 00000000..b1866d7b --- /dev/null +++ b/tests/gentest/divnum.1.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/divnum.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2707 + +. ${srcdir}/defs + +cat <<\EOF >in +Initial divnum +divert(1) +Diversion one: divnum +divert(2) +Diversion two: divnum +divert +EOF + +cat <<\EOF >ok +Initial 0 + + +Diversion one: 1 + +Diversion two: 2 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/dnl.1.m4 b/tests/gentest/dnl.1.m4 new file mode 100755 index 00000000..5d0d7632 --- /dev/null +++ b/tests/gentest/dnl.1.m4 @@ -0,0 +1,20 @@ +#!/bin/sh + +# gentest/dnl.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1857 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. +foo +EOF + +cat <<\EOF >ok +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/dnl.1.test b/tests/gentest/dnl.1.test new file mode 100755 index 00000000..f27916b3 --- /dev/null +++ b/tests/gentest/dnl.1.test @@ -0,0 +1,20 @@ +#!/bin/sh + +# gentest/dnl.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1857 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. +foo +EOF + +cat <<\EOF >ok +Macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/dumpdef.1.m4 b/tests/gentest/dumpdef.1.m4 new file mode 100755 index 00000000..bc31e1df --- /dev/null +++ b/tests/gentest/dumpdef.1.m4 @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/dumpdef.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1660 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +dumpdef(`foo') +dumpdef(`define') +EOF + +cat <<\EOF >ok + + + +EOF + +cat <<\EOF >okerr +foo: `Hello world.' +define: <define> +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/dumpdef.1.test b/tests/gentest/dumpdef.1.test new file mode 100755 index 00000000..c2a00ded --- /dev/null +++ b/tests/gentest/dumpdef.1.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/dumpdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1660 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello world.') +dumpdef(`foo') +dumpdef(`define') +EOF + +cat <<\EOF >ok + + + +EOF + +cat <<\EOF >okerr +foo: `Hello world.' +define: <define> +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/errprint.1.m4 b/tests/gentest/errprint.1.m4 new file mode 100755 index 00000000..107ef789 --- /dev/null +++ b/tests/gentest/errprint.1.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/errprint.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3426 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`Illegal arguments to forloop +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +Illegal arguments to forloop +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/errprint.1.test b/tests/gentest/errprint.1.test new file mode 100755 index 00000000..b703dd30 --- /dev/null +++ b/tests/gentest/errprint.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/errprint.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3426 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`Illegal arguments to forloop +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +Illegal arguments to forloop +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/errprint.2.m4 b/tests/gentest/errprint.2.m4 new file mode 100755 index 00000000..5259782d --- /dev/null +++ b/tests/gentest/errprint.2.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/errprint.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3451 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`m4:'__file__:__line__: `Input error +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4:in:1: Input error +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/errprint.2.test b/tests/gentest/errprint.2.test new file mode 100755 index 00000000..4ca64136 --- /dev/null +++ b/tests/gentest/errprint.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/errprint.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3451 + +. ${srcdir}/defs + +cat <<\EOF >in +errprint(`m4:'__file__:__line__: `Input error +') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4:in:1: Input error +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/esyscmd.1.m4 b/tests/gentest/esyscmd.1.m4 new file mode 100755 index 00000000..856620e4 --- /dev/null +++ b/tests/gentest/esyscmd.1.m4 @@ -0,0 +1,22 @@ +#!/bin/sh + +# gentest/esyscmd.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3315 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`vice', `esyscmd(grep Vice ../Makefile)') +vice +EOF + +cat <<\EOF >ok + +# Ty Coon, President of Vice + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/esyscmd.1.test b/tests/gentest/esyscmd.1.test new file mode 100755 index 00000000..8d609baf --- /dev/null +++ b/tests/gentest/esyscmd.1.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# gentest/esyscmd.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3315 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`vice', `esyscmd(grep Vice ../Makefile)') +vice +EOF + +cat <<\EOF >ok + +# Ty Coon, President of Vice + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/eval.1.m4 b/tests/gentest/eval.1.m4 new file mode 100755 index 00000000..b3d38cc3 --- /dev/null +++ b/tests/gentest/eval.1.m4 @@ -0,0 +1,38 @@ +#!/bin/sh + +# gentest/eval.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3199 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(-3 * 5) +eval(index(`Hello world', `llo') >= 0) +define(`square', `eval(($1)**2)') +square(9) +square(square(5)+1) +define(`foo', `666') +eval(`foo'/6) +eval(foo/6) +EOF + +cat <<\EOF >ok +-15 +1 + +81 +676 + + +111 +EOF + +cat <<\EOF >okerr +in:7: m4: Bad expression in eval: foo/6 +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/eval.1.test b/tests/gentest/eval.1.test new file mode 100755 index 00000000..56f916c2 --- /dev/null +++ b/tests/gentest/eval.1.test @@ -0,0 +1,38 @@ +#!/bin/sh + +# gentest/eval.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3199 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(-3 * 5) +eval(index(`Hello world', `llo') >= 0) +define(`square', `eval(($1)**2)') +square(9) +square(square(5)+1) +define(`foo', `666') +eval(`foo'/6) +eval(foo/6) +EOF + +cat <<\EOF >ok +-15 +1 + +81 +676 + + +111 +EOF + +cat <<\EOF >okerr +in:7: m4: Bad expression in eval: foo/6 +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/eval.2.m4 b/tests/gentest/eval.2.m4 new file mode 100755 index 00000000..bd394eb4 --- /dev/null +++ b/tests/gentest/eval.2.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/eval.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3230 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(666, 10) +eval(666, 11) +eval(666, 6) +eval(666, 6, 10) +eval(-666, 6, 10) +EOF + +cat <<\EOF >ok +666 +556 +3030 +0000003030 +-000003030 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/eval.2.test b/tests/gentest/eval.2.test new file mode 100755 index 00000000..abc9fbb6 --- /dev/null +++ b/tests/gentest/eval.2.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/eval.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3230 + +. ${srcdir}/defs + +cat <<\EOF >in +eval(666, 10) +eval(666, 11) +eval(666, 6) +eval(666, 6, 10) +eval(-666, 6, 10) +EOF + +cat <<\EOF >ok +666 +556 +3030 +0000003030 +-000003030 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/format.1.m4 b/tests/gentest/format.1.m4 new file mode 100755 index 00000000..ddfdb7f6 --- /dev/null +++ b/tests/gentest/format.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/format.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3035 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `The brown fox jumped over the lazy dog') +format(`The string "%s" is %d characters long', foo, len(foo)) +EOF + +cat <<\EOF >ok + +The string "The brown fox jumped over the lazy dog" is 38 characters long +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/format.1.test b/tests/gentest/format.1.test new file mode 100755 index 00000000..84c50d0a --- /dev/null +++ b/tests/gentest/format.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/format.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3035 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `The brown fox jumped over the lazy dog') +format(`The string "%s" is %d characters long', foo, len(foo)) +EOF + +cat <<\EOF >ok + +The string "The brown fox jumped over the lazy dog" is 38 characters long +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/ifdef.1.m4 b/tests/gentest/ifdef.1.m4 new file mode 100755 index 00000000..721608c0 --- /dev/null +++ b/tests/gentest/ifdef.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/ifdef.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1440 + +. ${srcdir}/defs + +cat <<\EOF >in +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +define(`foo', `') +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +EOF + +cat <<\EOF >ok +foo is not defined + +foo is defined +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/ifdef.1.test b/tests/gentest/ifdef.1.test new file mode 100755 index 00000000..fb9951c7 --- /dev/null +++ b/tests/gentest/ifdef.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/ifdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1440 + +. ${srcdir}/defs + +cat <<\EOF >in +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +define(`foo', `') +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +EOF + +cat <<\EOF >ok +foo is not defined + +foo is defined +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/ifelse.1.m4 b/tests/gentest/ifelse.1.m4 new file mode 100755 index 00000000..0d6fbcf0 --- /dev/null +++ b/tests/gentest/ifelse.1.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/ifelse.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1478 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(`foo', `bar', `true') +ifelse(`foo', `foo', `true') +ifelse(`foo', `bar', `true', `false') +ifelse(`foo', `foo', `true', `false') +EOF + +cat <<\EOF >ok + +true +false +true +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/ifelse.1.test b/tests/gentest/ifelse.1.test new file mode 100755 index 00000000..851c3005 --- /dev/null +++ b/tests/gentest/ifelse.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/ifelse.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1478 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(`foo', `bar', `true') +ifelse(`foo', `foo', `true') +ifelse(`foo', `bar', `true', `false') +ifelse(`foo', `foo', `true', `false') +EOF + +cat <<\EOF >ok + +true +false +true +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/ifelse.2.m4 b/tests/gentest/ifelse.2.m4 new file mode 100755 index 00000000..0cf36999 --- /dev/null +++ b/tests/gentest/ifelse.2.m4 @@ -0,0 +1,19 @@ +#!/bin/sh + +# gentest/ifelse.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1497 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +EOF + +cat <<\EOF >ok +seventh +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/ifelse.2.test b/tests/gentest/ifelse.2.test new file mode 100755 index 00000000..2573945b --- /dev/null +++ b/tests/gentest/ifelse.2.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# gentest/ifelse.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1497 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +EOF + +cat <<\EOF >ok +seventh +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/include.1.m4 b/tests/gentest/include.1.m4 new file mode 100755 index 00000000..e2912c84 --- /dev/null +++ b/tests/gentest/include.1.m4 @@ -0,0 +1,26 @@ +#!/bin/sh + +# gentest/include.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2454 + +. ${srcdir}/defs + +cat <<\EOF >in +include(`no-such-file') +sinclude(`no-such-file') +EOF + +cat <<\EOF >ok + + +EOF + +cat <<\EOF >okerr +in:1: m4: Cannot open no-such-file: No such file or directory +EOF + +M4PATH=$srcdir $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/include.1.test b/tests/gentest/include.1.test new file mode 100755 index 00000000..55e186eb --- /dev/null +++ b/tests/gentest/include.1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# gentest/include.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2454 + +. ${srcdir}/defs + +cat <<\EOF >in +include(`no-such-file') +sinclude(`no-such-file') +EOF + +cat <<\EOF >ok + + +EOF + +cat <<\EOF >okerr +in:1: m4: Cannot open no-such-file: No such file or directory +EOF + +M4PATH=$srcdir $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/include.2.m4 b/tests/gentest/include.2.m4 new file mode 100755 index 00000000..15a2ea64 --- /dev/null +++ b/tests/gentest/include.2.m4 @@ -0,0 +1,24 @@ +#!/bin/sh + +# gentest/include.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2474 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `FOO') +include(`incl.m4') +EOF + +cat <<\EOF >ok + +Include file start +FOO +Include file end + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/include.2.test b/tests/gentest/include.2.test new file mode 100755 index 00000000..9257157c --- /dev/null +++ b/tests/gentest/include.2.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# gentest/include.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2474 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `FOO') +include(`incl.m4') +EOF + +cat <<\EOF >ok + +Include file start +FOO +Include file end + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/include.3.m4 b/tests/gentest/include.3.m4 new file mode 100755 index 00000000..0f286a81 --- /dev/null +++ b/tests/gentest/include.3.m4 @@ -0,0 +1,24 @@ +#!/bin/sh + +# gentest/include.3.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2489 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', include(`incl.m4')) +This is `bar': >>>bar<<< +EOF + +cat <<\EOF >ok + +This is bar: >>>Include file start +foo +Include file end +<<< +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/include.3.test b/tests/gentest/include.3.test new file mode 100755 index 00000000..19c911b2 --- /dev/null +++ b/tests/gentest/include.3.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# gentest/include.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2489 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', include(`incl.m4')) +This is `bar': >>>bar<<< +EOF + +cat <<\EOF >ok + +This is bar: >>>Include file start +foo +Include file end +<<< +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/incr.1.m4 b/tests/gentest/incr.1.m4 new file mode 100755 index 00000000..16035bd3 --- /dev/null +++ b/tests/gentest/incr.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/incr.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3105 + +. ${srcdir}/defs + +cat <<\EOF >in +incr(4) +decr(7) +EOF + +cat <<\EOF >ok +5 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/incr.1.test b/tests/gentest/incr.1.test new file mode 100755 index 00000000..d9da8faa --- /dev/null +++ b/tests/gentest/incr.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/incr.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3105 + +. ${srcdir}/defs + +cat <<\EOF >in +incr(4) +decr(7) +EOF + +cat <<\EOF >ok +5 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/index.1.m4 b/tests/gentest/index.1.m4 new file mode 100755 index 00000000..28771378 --- /dev/null +++ b/tests/gentest/index.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/index.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2821 + +. ${srcdir}/defs + +cat <<\EOF >in +index(`gnus, gnats, and armadillos', `nat') +index(`gnus, gnats, and armadillos', `dag') +EOF + +cat <<\EOF >ok +7 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/index.1.test b/tests/gentest/index.1.test new file mode 100755 index 00000000..2226ab97 --- /dev/null +++ b/tests/gentest/index.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/index.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2821 + +. ${srcdir}/defs + +cat <<\EOF >in +index(`gnus, gnats, and armadillos', `nat') +index(`gnus, gnats, and armadillos', `dag') +EOF + +cat <<\EOF >ok +7 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/indir.1.m4 b/tests/gentest/indir.1.m4 new file mode 100755 index 00000000..e1714a5b --- /dev/null +++ b/tests/gentest/indir.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/indir.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1369 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`$$internal$macro', `Internal macro (name `$0')') +$$internal$macro +indir(`$$internal$macro') +EOF + +cat <<\EOF >ok + +$$internal$macro +Internal macro (name $$internal$macro) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/indir.1.test b/tests/gentest/indir.1.test new file mode 100755 index 00000000..ddb86909 --- /dev/null +++ b/tests/gentest/indir.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/indir.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1369 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`$$internal$macro', `Internal macro (name `$0')') +$$internal$macro +indir(`$$internal$macro') +EOF + +cat <<\EOF >ok + +$$internal$macro +Internal macro (name $$internal$macro) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/len.1.m4 b/tests/gentest/len.1.m4 new file mode 100755 index 00000000..1fa71023 --- /dev/null +++ b/tests/gentest/len.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/len.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2795 + +. ${srcdir}/defs + +cat <<\EOF >in +len() +len(`abcdef') +EOF + +cat <<\EOF >ok +0 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/len.1.test b/tests/gentest/len.1.test new file mode 100755 index 00000000..8799457a --- /dev/null +++ b/tests/gentest/len.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/len.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2795 + +. ${srcdir}/defs + +cat <<\EOF >in +len() +len(`abcdef') +EOF + +cat <<\EOF >ok +0 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/loops.1.m4 b/tests/gentest/loops.1.m4 new file mode 100755 index 00000000..791e2560 --- /dev/null +++ b/tests/gentest/loops.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/loops.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1534 + +. ${srcdir}/defs + +cat <<\EOF >in +shift +shift(bar) +shift(foo, bar, baz) +EOF + +cat <<\EOF >ok + + +bar,baz +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/loops.1.test b/tests/gentest/loops.1.test new file mode 100755 index 00000000..bf2b5264 --- /dev/null +++ b/tests/gentest/loops.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/loops.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1534 + +. ${srcdir}/defs + +cat <<\EOF >in +shift +shift(bar) +shift(foo, bar, baz) +EOF + +cat <<\EOF >ok + + +bar,baz +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/loops.2.m4 b/tests/gentest/loops.2.m4 new file mode 100755 index 00000000..88c305f5 --- /dev/null +++ b/tests/gentest/loops.2.m4 @@ -0,0 +1,26 @@ +#!/bin/sh + +# gentest/loops.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1546 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', + `reverse(shift($@)), `$1'')') +reverse +reverse(foo) +reverse(foo, bar, gnats, and gnus) +EOF + +cat <<\EOF >ok + + +foo +and gnus, gnats, bar, foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/loops.2.test b/tests/gentest/loops.2.test new file mode 100755 index 00000000..5e38e47e --- /dev/null +++ b/tests/gentest/loops.2.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# gentest/loops.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1546 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', + `reverse(shift($@)), `$1'')') +reverse +reverse(foo) +reverse(foo, bar, gnats, and gnus) +EOF + +cat <<\EOF >ok + + +foo +and gnus, gnats, bar, foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/m4exit.1.m4 b/tests/gentest/m4exit.1.m4 new file mode 100755 index 00000000..7ba446b1 --- /dev/null +++ b/tests/gentest/m4exit.1.m4 @@ -0,0 +1,26 @@ +#!/bin/sh + +# gentest/m4exit.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3474 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +fatal_error(`This is a BAD one, buster') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4: in: 3: fatal error: This is a BAD one, buster +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/m4exit.1.test b/tests/gentest/m4exit.1.test new file mode 100755 index 00000000..43a4b004 --- /dev/null +++ b/tests/gentest/m4exit.1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# gentest/m4exit.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3474 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +fatal_error(`This is a BAD one, buster') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4: in: 3: fatal error: This is a BAD one, buster +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/m4wrap.1.m4 b/tests/gentest/m4wrap.1.m4 new file mode 100755 index 00000000..a8315641 --- /dev/null +++ b/tests/gentest/m4wrap.1.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/m4wrap.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2395 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleanup', `This is the `cleanup' actions. +') +m4wrap(`cleanup') +This is the first and last normal input line. +EOF + +cat <<\EOF >ok + + +This is the first and last normal input line. +This is the cleanup actions. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/m4wrap.1.test b/tests/gentest/m4wrap.1.test new file mode 100755 index 00000000..c6327beb --- /dev/null +++ b/tests/gentest/m4wrap.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/m4wrap.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2395 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleanup', `This is the `cleanup' actions. +') +m4wrap(`cleanup') +This is the first and last normal input line. +EOF + +cat <<\EOF >ok + + +This is the first and last normal input line. +This is the cleanup actions. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/patsubst.1.m4 b/tests/gentest/patsubst.1.m4 new file mode 100755 index 00000000..1b39ecba --- /dev/null +++ b/tests/gentest/patsubst.1.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/patsubst.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2983 + +. ${srcdir}/defs + +cat <<\EOF >in +patsubst(`GNUs not Unix', `^', `OBS: ') +patsubst(`GNUs not Unix', `\<', `OBS: ') +patsubst(`GNUs not Unix', `\w*', `(\&)') +patsubst(`GNUs not Unix', `\w+', `(\&)') +patsubst(`GNUs not Unix', `[A-Z][a-z]+') +EOF + +cat <<\EOF >ok +OBS: GNUs not Unix +OBS: GNUs OBS: not OBS: Unix +(GNUs)() (not)() (Unix) +(GNUs) (not) (Unix) +GN not +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/patsubst.1.test b/tests/gentest/patsubst.1.test new file mode 100755 index 00000000..6213ef87 --- /dev/null +++ b/tests/gentest/patsubst.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/patsubst.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2983 + +. ${srcdir}/defs + +cat <<\EOF >in +patsubst(`GNUs not Unix', `^', `OBS: ') +patsubst(`GNUs not Unix', `\<', `OBS: ') +patsubst(`GNUs not Unix', `\w*', `(\&)') +patsubst(`GNUs not Unix', `\w+', `(\&)') +patsubst(`GNUs not Unix', `[A-Z][a-z]+') +EOF + +cat <<\EOF >ok +OBS: GNUs not Unix +OBS: GNUs OBS: not OBS: Unix +(GNUs)() (not)() (Unix) +(GNUs) (not) (Unix) +GN not +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/patsubst.2.m4 b/tests/gentest/patsubst.2.m4 new file mode 100755 index 00000000..f8644359 --- /dev/null +++ b/tests/gentest/patsubst.2.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/patsubst.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3000 + +. ${srcdir}/defs + +cat <<\EOF >in +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') +EOF + +cat <<\EOF >ok +Gnus Not Unix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/patsubst.2.test b/tests/gentest/patsubst.2.test new file mode 100755 index 00000000..b31e4d80 --- /dev/null +++ b/tests/gentest/patsubst.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/patsubst.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3000 + +. ${srcdir}/defs + +cat <<\EOF >in +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') +EOF + +cat <<\EOF >ok +Gnus Not Unix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.1.m4 b/tests/gentest/pseudoar.1.m4 new file mode 100755 index 00000000..29721fa1 --- /dev/null +++ b/tests/gentest/pseudoar.1.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/pseudoar.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1100 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`nargs', `$#') +nargs +nargs() +nargs(arg1, arg2, arg3) +EOF + +cat <<\EOF >ok + +0 +1 +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.1.test b/tests/gentest/pseudoar.1.test new file mode 100755 index 00000000..50260e65 --- /dev/null +++ b/tests/gentest/pseudoar.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/pseudoar.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1100 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`nargs', `$#') +nargs +nargs() +nargs(arg1, arg2, arg3) +EOF + +cat <<\EOF >ok + +0 +1 +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.2.m4 b/tests/gentest/pseudoar.2.m4 new file mode 100755 index 00000000..47231cf4 --- /dev/null +++ b/tests/gentest/pseudoar.2.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/pseudoar.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1114 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$*') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.2.test b/tests/gentest/pseudoar.2.test new file mode 100755 index 00000000..ca939b81 --- /dev/null +++ b/tests/gentest/pseudoar.2.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/pseudoar.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1114 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$*') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.3.m4 b/tests/gentest/pseudoar.3.m4 new file mode 100755 index 00000000..997641f3 --- /dev/null +++ b/tests/gentest/pseudoar.3.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/pseudoar.3.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1125 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$@') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.3.test b/tests/gentest/pseudoar.3.test new file mode 100755 index 00000000..b29b17fc --- /dev/null +++ b/tests/gentest/pseudoar.3.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/pseudoar.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1125 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$@') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.4.m4 b/tests/gentest/pseudoar.4.m4 new file mode 100755 index 00000000..68b7b6ef --- /dev/null +++ b/tests/gentest/pseudoar.4.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/pseudoar.4.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1135 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo1', `$*') +define(`echo2', `$@') +define(`foo', `This is macro `foo'.') +echo1(foo) +echo2(foo) +EOF + +cat <<\EOF >ok + + + +This is macro This is macro foo.. +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.4.test b/tests/gentest/pseudoar.4.test new file mode 100755 index 00000000..81616f26 --- /dev/null +++ b/tests/gentest/pseudoar.4.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/pseudoar.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1135 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo1', `$*') +define(`echo2', `$@') +define(`foo', `This is macro `foo'.') +echo1(foo) +echo2(foo) +EOF + +cat <<\EOF >ok + + + +This is macro This is macro foo.. +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.5.m4 b/tests/gentest/pseudoar.5.m4 new file mode 100755 index 00000000..8c01d6f7 --- /dev/null +++ b/tests/gentest/pseudoar.5.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/pseudoar.5.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1155 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `$$$ hello $$$') +foo +EOF + +cat <<\EOF >ok + +$$$ hello $$$ +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pseudoar.5.test b/tests/gentest/pseudoar.5.test new file mode 100755 index 00000000..e90de1fa --- /dev/null +++ b/tests/gentest/pseudoar.5.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/pseudoar.5.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1155 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `$$$ hello $$$') +foo +EOF + +cat <<\EOF >ok + +$$$ hello $$$ +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pushdef.1.m4 b/tests/gentest/pushdef.1.m4 new file mode 100755 index 00000000..ac11f585 --- /dev/null +++ b/tests/gentest/pushdef.1.m4 @@ -0,0 +1,33 @@ +#!/bin/sh + +# gentest/pushdef.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1294 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +popdef(`foo') +foo +popdef(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Expansion one. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pushdef.1.test b/tests/gentest/pushdef.1.test new file mode 100755 index 00000000..d934f422 --- /dev/null +++ b/tests/gentest/pushdef.1.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# gentest/pushdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1294 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +popdef(`foo') +foo +popdef(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Expansion one. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pushdef.2.m4 b/tests/gentest/pushdef.2.m4 new file mode 100755 index 00000000..07eb0c79 --- /dev/null +++ b/tests/gentest/pushdef.2.m4 @@ -0,0 +1,33 @@ +#!/bin/sh + +# gentest/pushdef.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1318 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +define(`foo', `Second expansion two.') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Second expansion two. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/pushdef.2.test b/tests/gentest/pushdef.2.test new file mode 100755 index 00000000..7d43770f --- /dev/null +++ b/tests/gentest/pushdef.2.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# gentest/pushdef.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1318 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +define(`foo', `Second expansion two.') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Second expansion two. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/regexp.1.m4 b/tests/gentest/regexp.1.m4 new file mode 100755 index 00000000..d27cf8e7 --- /dev/null +++ b/tests/gentest/regexp.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/regexp.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2853 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\<[a-z]\w+') +regexp(`GNUs not Unix', `\<Q\w*') +EOF + +cat <<\EOF >ok +5 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/regexp.1.test b/tests/gentest/regexp.1.test new file mode 100755 index 00000000..3427751e --- /dev/null +++ b/tests/gentest/regexp.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/regexp.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2853 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\<[a-z]\w+') +regexp(`GNUs not Unix', `\<Q\w*') +EOF + +cat <<\EOF >ok +5 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/regexp.2.m4 b/tests/gentest/regexp.2.m4 new file mode 100755 index 00000000..a75bdc6f --- /dev/null +++ b/tests/gentest/regexp.2.m4 @@ -0,0 +1,19 @@ +#!/bin/sh + +# gentest/regexp.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2865 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +EOF + +cat <<\EOF >ok +*** Unix *** nix *** +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/regexp.2.test b/tests/gentest/regexp.2.test new file mode 100755 index 00000000..c3ff8894 --- /dev/null +++ b/tests/gentest/regexp.2.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# gentest/regexp.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2865 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +EOF + +cat <<\EOF >ok +*** Unix *** nix *** +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/substr.1.m4 b/tests/gentest/substr.1.m4 new file mode 100755 index 00000000..6354c598 --- /dev/null +++ b/tests/gentest/substr.1.m4 @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/substr.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2891 + +. ${srcdir}/defs + +cat <<\EOF >in +substr(`gnus, gnats, and armadillos', 6) +substr(`gnus, gnats, and armadillos', 6, 5) +EOF + +cat <<\EOF >ok +gnats, and armadillos +gnats +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/substr.1.test b/tests/gentest/substr.1.test new file mode 100755 index 00000000..964ab0eb --- /dev/null +++ b/tests/gentest/substr.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# gentest/substr.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2891 + +. ${srcdir}/defs + +cat <<\EOF >in +substr(`gnus, gnats, and armadillos', 6) +substr(`gnus, gnats, and armadillos', 6, 5) +EOF + +cat <<\EOF >ok +gnats, and armadillos +gnats +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/sysval.1.m4 b/tests/gentest/sysval.1.m4 new file mode 100755 index 00000000..f1ffeb7b --- /dev/null +++ b/tests/gentest/sysval.1.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/sysval.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3346 + +. ${srcdir}/defs + +cat <<\EOF >in +syscmd(`false') +ifelse(sysval, 0, zero, non-zero) +syscmd(`true') +sysval +EOF + +cat <<\EOF >ok + +non-zero + +0 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/sysval.1.test b/tests/gentest/sysval.1.test new file mode 100755 index 00000000..6e101fd7 --- /dev/null +++ b/tests/gentest/sysval.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/sysval.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3346 + +. ${srcdir}/defs + +cat <<\EOF >in +syscmd(`false') +ifelse(sysval, 0, zero, non-zero) +syscmd(`true') +sysval +EOF + +cat <<\EOF >ok + +non-zero + +0 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/trace.1.m4 b/tests/gentest/trace.1.m4 new file mode 100755 index 00000000..eae2a55e --- /dev/null +++ b/tests/gentest/trace.1.m4 @@ -0,0 +1,33 @@ +#!/bin/sh + +# gentest/trace.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1705 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello World.') +define(`echo', `$@') +traceon(`foo', `echo') +foo +echo(gnus, and gnats) +EOF + +cat <<\EOF >ok + + + +Hello World. +gnus,and gnats +EOF + +cat <<\EOF >okerr +m4trace: -1- foo -> `Hello World.' +m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/trace.1.test b/tests/gentest/trace.1.test new file mode 100755 index 00000000..ef1cb312 --- /dev/null +++ b/tests/gentest/trace.1.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# gentest/trace.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1705 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello World.') +define(`echo', `$@') +traceon(`foo', `echo') +foo +echo(gnus, and gnats) +EOF + +cat <<\EOF >ok + + + +Hello World. +gnus,and gnats +EOF + +cat <<\EOF >okerr +m4trace: -1- foo -> `Hello World.' +m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/gentest/translit.1.m4 b/tests/gentest/translit.1.m4 new file mode 100755 index 00000000..4ac2bd7a --- /dev/null +++ b/tests/gentest/translit.1.m4 @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/translit.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2932 + +. ${srcdir}/defs + +cat <<\EOF >in +translit(`GNUs not Unix', `A-Z') +translit(`GNUs not Unix', `a-z', `A-Z') +translit(`GNUs not Unix', `A-Z', `z-a') +EOF + +cat <<\EOF >ok +s not nix +GNUS NOT UNIX +tmfs not fnix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/translit.1.test b/tests/gentest/translit.1.test new file mode 100755 index 00000000..e650bbdf --- /dev/null +++ b/tests/gentest/translit.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# gentest/translit.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2932 + +. ${srcdir}/defs + +cat <<\EOF >in +translit(`GNUs not Unix', `A-Z') +translit(`GNUs not Unix', `a-z', `A-Z') +translit(`GNUs not Unix', `A-Z', `z-a') +EOF + +cat <<\EOF >ok +s not nix +GNUS NOT UNIX +tmfs not fnix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undefine.1.m4 b/tests/gentest/undefine.1.m4 new file mode 100755 index 00000000..cd7db2ad --- /dev/null +++ b/tests/gentest/undefine.1.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/undefine.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1186 + +. ${srcdir}/defs + +cat <<\EOF >in +foo +define(`foo', `expansion text') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok +foo + +expansion text + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undefine.1.test b/tests/gentest/undefine.1.test new file mode 100755 index 00000000..d196e530 --- /dev/null +++ b/tests/gentest/undefine.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/undefine.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1186 + +. ${srcdir}/defs + +cat <<\EOF >in +foo +define(`foo', `expansion text') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok +foo + +expansion text + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undivert.1.m4 b/tests/gentest/undivert.1.m4 new file mode 100755 index 00000000..db869a32 --- /dev/null +++ b/tests/gentest/undivert.1.m4 @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/undivert.1.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2631 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +undivert(1) +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undivert.1.test b/tests/gentest/undivert.1.test new file mode 100755 index 00000000..3d04dc8b --- /dev/null +++ b/tests/gentest/undivert.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# gentest/undivert.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2631 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +undivert(1) +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undivert.2.m4 b/tests/gentest/undivert.2.m4 new file mode 100755 index 00000000..0663e0dd --- /dev/null +++ b/tests/gentest/undivert.2.m4 @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/undivert.2.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2655 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted first. +divert(0)undivert(1)dnl +undivert(1) +divert(1) +This text is also diverted but not appended. +divert(0)undivert(1)dnl +EOF + +cat <<\EOF >ok + +This text is diverted first. + + +This text is also diverted but not appended. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undivert.2.test b/tests/gentest/undivert.2.test new file mode 100755 index 00000000..6a84ecc4 --- /dev/null +++ b/tests/gentest/undivert.2.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# gentest/undivert.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2655 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted first. +divert(0)undivert(1)dnl +undivert(1) +divert(1) +This text is also diverted but not appended. +divert(0)undivert(1)dnl +EOF + +cat <<\EOF >ok + +This text is diverted first. + + +This text is also diverted but not appended. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undivert.3.m4 b/tests/gentest/undivert.3.m4 new file mode 100755 index 00000000..d0b92cae --- /dev/null +++ b/tests/gentest/undivert.3.m4 @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/undivert.3.m4 is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2681 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', `BAR') +undivert(`foo') +include(`foo') +EOF + +cat <<\EOF >ok + +bar + +BAR + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/gentest/undivert.3.test b/tests/gentest/undivert.3.test new file mode 100755 index 00000000..f6d22551 --- /dev/null +++ b/tests/gentest/undivert.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# gentest/undivert.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2681 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', `BAR') +undivert(`foo') +include(`foo') +EOF + +cat <<\EOF >ok + +bar + +BAR + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/get-them b/tests/get-them new file mode 100755 index 00000000..ca42991a --- /dev/null +++ b/tests/get-them @@ -0,0 +1,112 @@ +#!/bin/sh +# Extract all examples from the manual source. +# Copyright (C) 1992 Free Software Foundation, Inc. + +# This script is for use with GNU awk. + +FILE=${1-/dev/null} + +${AWK-gawk} ' + +BEGIN { + node = ""; + seq = -1; + count = 0; + file = "NONE"; +} + +/^@node / { + if (seq > 0) + printf(" -- %d test%s", seq, seq == 1 ? "" : "s"); + if (seq >= 0) + printf("\n"); + + split($0, tmp, ","); + Node = substr(tmp[1], 7); + node = tolower(Node); + gsub(" ", "", node); + if (length(node) > 8) + printf("Node: %s - truncated", node); + else + printf("Node: %s ", node); + node = substr(node, 1, 8); + seq = 0; +} + +/^@comment ignore$/ { + getline; + next; +} + +/^@example$/, /^@end example$/ { + if (seq < 0) + next; + if ($0 ~ /^@example$/) { + if (count > 0) + close (file); + seq++; + count++; + o = 0; + e = 0; + error_flag = 0; + i = 0; + include_flag = 0; + file = sprintf("%s.%d.test", node, seq); + printf ("#!/bin/sh\n\n") > file; + printf ("# %s is part of the GNU m4 testsuite\n", file) >> file; + printf ("# generated from example in %s line %d\n\n", FILENAME, NR) >>file; + printf (". ${srcdir}/defs\n") >> file; + next; + } + if ($0 ~ /^@end example$/) { + printthem(input, i, "in"); + printthem(output, o, "ok"); + printthem(error, e, "okerr"); + printf ("\n") >> file; + if (include_flag == 1) printf ("M4PATH=$srcdir ") >> file; + printf ("$M4 -d in >out") >> file; + if (error_flag == 1) printf (" 2>err") >> file; + if (error_flag == 1) printf ("\nsed -e \"s, ../../src/m4:, m4:,\" err >sederr && mv sederr err") >> file; + printf ("\n\n$CMP -s out ok") >> file; + if (error_flag == 1) printf (" && $CMP -s err okerr") >> file; + printf ("\n\n") >> file; + next; + } + if ($0 ~ /^\^D$/) + next; + if ($0 ~ /^@result\{\}/) { + gsub(/^@result\{\}/, "", $0); + output[o++] = $0; + } + else if ($0 ~ /^@error\{\}/) { + gsub(/^@error\{\}/, "", $0); + error[e++] = $0; + error_flag = 1; + } + else { + input[i++] = $0; + if ($0 ~ /s*include\(/) include_flag = 1; + } +} + +END { + printf("\n"); +} + +function printthem(thearray, thecounter, thefile) { + if ((thecounter>0) || (thefile=="ok")) { + printf ("\ncat <<\\EOF >%s\n", thefile) >> file; + for (j=0; j<thecounter; j++) { + gsub("@{", "{", thearray[j]); + gsub("@}", "}", thearray[j]); + gsub("@@", "@", thearray[j]); + gsub("@comment.*", "", thearray[j]); + printf ("%s\n", thearray[j]) >> file; + } + printf ("EOF\n") >> file; + } +} + +' $FILE >/dev/null + +chmod +x *.[0-9].test diff --git a/tests/ifdef.1.test b/tests/ifdef.1.test new file mode 100755 index 00000000..9cb0935b --- /dev/null +++ b/tests/ifdef.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# ifdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1441 + +. ${srcdir}/defs + +cat <<\EOF >in +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +define(`foo', `') +ifdef(`foo', ``foo' is defined', ``foo' is not defined') +EOF + +cat <<\EOF >ok +foo is not defined + +foo is defined +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/ifelse.1.test b/tests/ifelse.1.test new file mode 100755 index 00000000..7942a0c2 --- /dev/null +++ b/tests/ifelse.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# ifelse.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1479 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(`foo', `bar', `true') +ifelse(`foo', `foo', `true') +ifelse(`foo', `bar', `true', `false') +ifelse(`foo', `foo', `true', `false') +EOF + +cat <<\EOF >ok + +true +false +true +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/ifelse.2.test b/tests/ifelse.2.test new file mode 100755 index 00000000..d2049f5d --- /dev/null +++ b/tests/ifelse.2.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# ifelse.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1498 + +. ${srcdir}/defs + +cat <<\EOF >in +ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh') +EOF + +cat <<\EOF >ok +seventh +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/incl.m4 b/tests/incl.m4 new file mode 100644 index 00000000..ab9572eb --- /dev/null +++ b/tests/incl.m4 @@ -0,0 +1,3 @@ +Include file start +foo +Include file end diff --git a/tests/include.1.test b/tests/include.1.test new file mode 100755 index 00000000..535a1292 --- /dev/null +++ b/tests/include.1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# include.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2455 + +. ${srcdir}/defs + +cat <<\EOF >in +include(`no-such-file') +sinclude(`no-such-file') +EOF + +cat <<\EOF >ok + + +EOF + +cat <<\EOF >okerr +in:1: m4: Cannot open no-such-file: No such file or directory +EOF + +M4PATH=$srcdir $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/include.2.test b/tests/include.2.test new file mode 100755 index 00000000..1e0c428f --- /dev/null +++ b/tests/include.2.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# include.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2475 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `FOO') +include(`incl.m4') +EOF + +cat <<\EOF >ok + +Include file start +FOO +Include file end + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/include.3.test b/tests/include.3.test new file mode 100755 index 00000000..edf228d0 --- /dev/null +++ b/tests/include.3.test @@ -0,0 +1,24 @@ +#!/bin/sh + +# include.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2490 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', include(`incl.m4')) +This is `bar': >>>bar<<< +EOF + +cat <<\EOF >ok + +This is bar: >>>Include file start +foo +Include file end +<<< +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + diff --git a/tests/incr.1.test b/tests/incr.1.test new file mode 100755 index 00000000..d20be4df --- /dev/null +++ b/tests/incr.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# incr.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3106 + +. ${srcdir}/defs + +cat <<\EOF >in +incr(4) +decr(7) +EOF + +cat <<\EOF >ok +5 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/index.1.test b/tests/index.1.test new file mode 100755 index 00000000..1cee65fa --- /dev/null +++ b/tests/index.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# index.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2822 + +. ${srcdir}/defs + +cat <<\EOF >in +index(`gnus, gnats, and armadillos', `nat') +index(`gnus, gnats, and armadillos', `dag') +EOF + +cat <<\EOF >ok +7 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/indir.1.test b/tests/indir.1.test new file mode 100755 index 00000000..3cbc0511 --- /dev/null +++ b/tests/indir.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# indir.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1370 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`$$internal$macro', `Internal macro (name `$0')') +$$internal$macro +indir(`$$internal$macro') +EOF + +cat <<\EOF >ok + +$$internal$macro +Internal macro (name $$internal$macro) +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/len.1.test b/tests/len.1.test new file mode 100755 index 00000000..a60bb1b0 --- /dev/null +++ b/tests/len.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# len.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2796 + +. ${srcdir}/defs + +cat <<\EOF >in +len() +len(`abcdef') +EOF + +cat <<\EOF >ok +0 +6 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/loops.1.test b/tests/loops.1.test new file mode 100755 index 00000000..3a872fc9 --- /dev/null +++ b/tests/loops.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# loops.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1535 + +. ${srcdir}/defs + +cat <<\EOF >in +shift +shift(bar) +shift(foo, bar, baz) +EOF + +cat <<\EOF >ok + + +bar,baz +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/loops.2.test b/tests/loops.2.test new file mode 100755 index 00000000..35e4db17 --- /dev/null +++ b/tests/loops.2.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# loops.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1547 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'', + `reverse(shift($@)), `$1'')') +reverse +reverse(foo) +reverse(foo, bar, gnats, and gnus) +EOF + +cat <<\EOF >ok + + +foo +and gnus, gnats, bar, foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/m4exit.1.test b/tests/m4exit.1.test new file mode 100755 index 00000000..c721d434 --- /dev/null +++ b/tests/m4exit.1.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# m4exit.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3475 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') +fatal_error(`This is a BAD one, buster') +EOF + +cat <<\EOF >ok + +EOF + +cat <<\EOF >okerr +m4: in: 3: fatal error: This is a BAD one, buster +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/m4wrap.1.test b/tests/m4wrap.1.test new file mode 100755 index 00000000..1a27ac3c --- /dev/null +++ b/tests/m4wrap.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# m4wrap.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2396 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`cleanup', `This is the `cleanup' actions. +') +m4wrap(`cleanup') +This is the first and last normal input line. +EOF + +cat <<\EOF >ok + + +This is the first and last normal input line. +This is the cleanup actions. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/mkconfig.sh b/tests/mkconfig.sh new file mode 100644 index 00000000..f2ebc782 --- /dev/null +++ b/tests/mkconfig.sh @@ -0,0 +1,4 @@ +#!/bin/sh +env >/tmp/env +sed -n -e '/^#define \(\(WITH\|ENABLE\)_.*\) \(.*\)$/s//define(\1, \3)dnl/p' config.h > tests/config.m4 +sed -n -e '/^#define \(\(WITH\|ENABLE\)_.*\) \(.*\)$/s//\1=\3/p' config.h > tests/config.sh diff --git a/tests/other-tests/discard-comments.m4 b/tests/other-tests/discard-comments.m4 new file mode 100644 index 00000000..95aebd27 --- /dev/null +++ b/tests/other-tests/discard-comments.m4 @@ -0,0 +1,7 @@ +This is not a comment # but this is. +# This line should dissappear completely. +This should not disappear. +changecom(`<!--', `-->') +html <!-- +comment + --> ends. diff --git a/tests/other-tests/discard-comments.test b/tests/other-tests/discard-comments.test new file mode 100755 index 00000000..2f6a4599 --- /dev/null +++ b/tests/other-tests/discard-comments.test @@ -0,0 +1,17 @@ +#!/bin/sh + +# discard-comments.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/other-tests/discard-comments.m4 >in + +cat <<\EOF >ok +This is not a comment This should not disappear. + +html ends. +EOF + +M4PATH=$srcdir:$srcdir/other-tests $M4 -c -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/tests/other-tests/gmp.m4 b/tests/other-tests/gmp.m4 new file mode 100644 index 00000000..b916ff69 --- /dev/null +++ b/tests/other-tests/gmp.m4 @@ -0,0 +1,10 @@ +divert(-1) +# forloop(i, from, to, stmt) + +define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') +define(`_forloop', + `$4`'ifelse($1, `$3', , + `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') +divert +forloop(`x', 1, 100, `2**x = eval(2**x) +') diff --git a/tests/other-tests/gmp.test b/tests/other-tests/gmp.test new file mode 100755 index 00000000..9382832a --- /dev/null +++ b/tests/other-tests/gmp.test @@ -0,0 +1,120 @@ +#!/bin/sh + +# gmp.test is part of the GNU m4 testsuite + +. ${srcdir}/defs +. ${srcdir}/config.sh + +# cannot perform test without --with-gmp +test -z "$WITH_GMP" && exit 77 + +cat ${srcdir}/other-tests/gmp.m4 >in + +cat <<\EOF >ok + +2**1 = 2 +2**2 = 4 +2**3 = 8 +2**4 = 16 +2**5 = 32 +2**6 = 64 +2**7 = 128 +2**8 = 256 +2**9 = 512 +2**10 = 1024 +2**11 = 2048 +2**12 = 4096 +2**13 = 8192 +2**14 = 16384 +2**15 = 32768 +2**16 = 65536 +2**17 = 131072 +2**18 = 262144 +2**19 = 524288 +2**20 = 1048576 +2**21 = 2097152 +2**22 = 4194304 +2**23 = 8388608 +2**24 = 16777216 +2**25 = 33554432 +2**26 = 67108864 +2**27 = 134217728 +2**28 = 268435456 +2**29 = 536870912 +2**30 = 1073741824 +2**31 = 2147483648 +2**32 = 4294967296 +2**33 = 8589934592 +2**34 = 17179869184 +2**35 = 34359738368 +2**36 = 68719476736 +2**37 = 137438953472 +2**38 = 274877906944 +2**39 = 549755813888 +2**40 = 1099511627776 +2**41 = 2199023255552 +2**42 = 4398046511104 +2**43 = 8796093022208 +2**44 = 17592186044416 +2**45 = 35184372088832 +2**46 = 70368744177664 +2**47 = 140737488355328 +2**48 = 281474976710656 +2**49 = 562949953421312 +2**50 = 1125899906842624 +2**51 = 2251799813685248 +2**52 = 4503599627370496 +2**53 = 9007199254740992 +2**54 = 18014398509481984 +2**55 = 36028797018963968 +2**56 = 72057594037927936 +2**57 = 144115188075855872 +2**58 = 288230376151711744 +2**59 = 576460752303423488 +2**60 = 1152921504606846976 +2**61 = 2305843009213693952 +2**62 = 4611686018427387904 +2**63 = 9223372036854775808 +2**64 = 18446744073709551616 +2**65 = 36893488147419103232 +2**66 = 73786976294838206464 +2**67 = 147573952589676412928 +2**68 = 295147905179352825856 +2**69 = 590295810358705651712 +2**70 = 1180591620717411303424 +2**71 = 2361183241434822606848 +2**72 = 4722366482869645213696 +2**73 = 9444732965739290427392 +2**74 = 18889465931478580854784 +2**75 = 37778931862957161709568 +2**76 = 75557863725914323419136 +2**77 = 151115727451828646838272 +2**78 = 302231454903657293676544 +2**79 = 604462909807314587353088 +2**80 = 1208925819614629174706176 +2**81 = 2417851639229258349412352 +2**82 = 4835703278458516698824704 +2**83 = 9671406556917033397649408 +2**84 = 19342813113834066795298816 +2**85 = 38685626227668133590597632 +2**86 = 77371252455336267181195264 +2**87 = 154742504910672534362390528 +2**88 = 309485009821345068724781056 +2**89 = 618970019642690137449562112 +2**90 = 1237940039285380274899124224 +2**91 = 2475880078570760549798248448 +2**92 = 4951760157141521099596496896 +2**93 = 9903520314283042199192993792 +2**94 = 19807040628566084398385987584 +2**95 = 39614081257132168796771975168 +2**96 = 79228162514264337593543950336 +2**97 = 158456325028528675187087900672 +2**98 = 316912650057057350374175801344 +2**99 = 633825300114114700748351602688 +2**100 = 1267650600228229401496703205376 + +EOF + +M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/tests/other-tests/import-environment.m4 b/tests/other-tests/import-environment.m4 new file mode 100644 index 00000000..f537df66 --- /dev/null +++ b/tests/other-tests/import-environment.m4 @@ -0,0 +1,4 @@ +`TEST'=TEST +`LANGUAGE'=LANGUAGE +`ZAPPED'=ZAPPED +`OVERRIDE'=OVERRIDE diff --git a/tests/other-tests/import-environment.test b/tests/other-tests/import-environment.test new file mode 100755 index 00000000..195434b5 --- /dev/null +++ b/tests/other-tests/import-environment.test @@ -0,0 +1,28 @@ +#!/bin/sh + +# import-environment.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +TEST='This is an environment variable' +export TEST + +ZAPPED='This is an environment variable which we will delete' +export ZAPPED + +OVERRIDE='This is an environment variable which we will change' +export OVERRIDE + +cat ${srcdir}/other-tests/import-environment.m4 >in + +cat <<\EOF >ok +TEST=This is an environment variable +LANGUAGE=C +ZAPPED=ZAPPED +OVERRIDE=It is changed. +EOF + +M4PATH=$srcdir:$srcdir/other-tests \ +$M4 --import-environment -UZAPPED -DOVERRIDE='It is changed.' -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/tests/other-tests/iso8859.m4 b/tests/other-tests/iso8859.m4 Binary files differnew file mode 100644 index 00000000..4ac1d196 --- /dev/null +++ b/tests/other-tests/iso8859.m4 diff --git a/tests/other-tests/iso8859.test b/tests/other-tests/iso8859.test new file mode 100755 index 00000000..f77dbb27 --- /dev/null +++ b/tests/other-tests/iso8859.test @@ -0,0 +1,31 @@ +#!/bin/sh + +# iso8859.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/other-tests/iso8859.m4 > in + +cat <<\EOF >ok +# Texting quotes +DEFINE +CHANGEQUOTE(«,») +0 TEST # TEST +1 test # test +2 «test» # «test» +3 ««test»» # ««test»» +CHANGEQUOTE(«««,»»») +0 TEST # TEST +1 «TEST» # «TEST» +2 ««TEST»» # ««TEST»» +3 test # test +# Test use of all iso8859 characters except NUL ` ' +Length of string is: 253 +Comparing strings: MATCH +# NUL does not pass through +This will be seen. +EOF + +M4PATH=$srcdir:$srcdir/other-tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/tests/other-tests/stackovf.test b/tests/other-tests/stackovf.test new file mode 100755 index 00000000..699c5bef --- /dev/null +++ b/tests/other-tests/stackovf.test @@ -0,0 +1,86 @@ +#!/bin/sh + +exit 77 + +# Script to verify that stack overflow is diagnosed properly when +# there is infinite macro call nesting. +# (causes coredump in m4-1.0.3) + +# On some systems the ulimit command is available in ksh or bash but not sh +(exec 2>/dev/null; ulimit -HSs 300) || { + for altshell in bash bsh ksh ; do + if (exec >/dev/null 2>&1; $altshell -c 'ulimit -HSs 300') && + test -z "$1" + then + echo "Using $altshell because it supports ulimit" + exec $altshell $0 running-with-$altshell + exit 9 + fi + done +} + +PATH=.:..:$PATH; export PATH; +: ${M4=../../src/m4} +type $M4 + +tmpfile=/tmp/t.$$ +trap 'rm -f $tmpfile; exit 1' 1 2 3 15 + +rm -f core +perl -e ' +# Generate nested define sequence +$max=1000000; +for ($i=0; $i<$max; $i++) { + print "define(X$i,\n"; +} +for ($i=$max-1; $i>=0; $i--) { + print "body with substance no. $i)dnl\n" +} +' | \ +( +# Limit the stack size if the shell we are running permits it +if (exec 2>/dev/null; ulimit -HSs 50) +then + (exec >/dev/null 2>&1; ulimit -v) && ulimitdashv=ok + ulimit -HSs 50 + #ulimit -HSd 8000 + #test -n "$ulimitdashv" && ulimit -HSv 8000 + echo "Stack limit is `ulimit -s`K"; + echo "Heap limit is `ulimit -d`K"; + test -n "$ulimitdashv" && + echo "VMem limit is `ulimit -v`K"; +else + echo "Can't reset stack limit - this may take a while..." +fi +strace -o /tmp/aaa $M4 -L999999999 > $tmpfile 2>&1 +) +result=$? +{ echo "Output from $M4:"; cat $tmpfile; } + +exitcode=1 +if test $result -eq 0 ; then + echo "TEST DID NOT WORK - m4 did not abort. Output:" +else + # See if stack overflow was diagnosed + case "`cat $tmpfile`" in + *overflow*) + echo "Test succeeded."; + exitcode=0 + ;; + *ut*of*emory*|*emory*xhausted) + echo "*** Test is INCONCLUSIVE (ran out of heap before stack overflow)"; + ;; + *) echo "*** Test FAILED. $M4 aborted unexpectedly. Output:"; + ;; + esac +fi + +if test -f core ; then + ls -l core + exitcode=1 +fi + +#(test $exitcode -ne 0) && + { echo "Output from $M4:"; cat $tmpfile; } + +exit $exitcode diff --git a/tests/other-tests/sync-lines.m4 b/tests/other-tests/sync-lines.m4 new file mode 100644 index 00000000..7cad389d --- /dev/null +++ b/tests/other-tests/sync-lines.m4 @@ -0,0 +1,12 @@ +syncoutput(on)dnl +# Several input lines, expanding to one +define(`foo', ``foo' line one. +`foo' line two. +`foo' line three.') xyz +foo +# Several input lines, expanding to none +define(`foo', ``foo' line one. +`foo' line two. +`foo' line three.')dnl +# one input line, expanding to several output lines +foo foo diff --git a/tests/other-tests/sync-lines.test b/tests/other-tests/sync-lines.test new file mode 100755 index 00000000..c151f669 --- /dev/null +++ b/tests/other-tests/sync-lines.test @@ -0,0 +1,35 @@ +#!/bin/sh + +# sync-lines.test is part of the GNU m4 testsuite + +. ${srcdir}/defs + +cat ${srcdir}/other-tests/sync-lines.m4 >in + +cat <<\EOF >ok +#line 2 "in" +# Several input lines, expanding to one +#line 5 + xyz +foo line one. +#line 6 +foo line two. +#line 6 +foo line three. +# Several input lines, expanding to none +#line 11 +# one input line, expanding to several output lines +foo line one. +#line 12 +foo line two. +#line 12 +foo line three. foo line one. +#line 12 +foo line two. +#line 12 +foo line three. +EOF + +M4PATH=$srcdir:$srcdir/other-tests $M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err +$CMP -s out ok diff --git a/tests/patsubst.1.test b/tests/patsubst.1.test new file mode 100755 index 00000000..152d961d --- /dev/null +++ b/tests/patsubst.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# patsubst.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2984 + +. ${srcdir}/defs + +cat <<\EOF >in +patsubst(`GNUs not Unix', `^', `OBS: ') +patsubst(`GNUs not Unix', `\<', `OBS: ') +patsubst(`GNUs not Unix', `\w*', `(\&)') +patsubst(`GNUs not Unix', `\w+', `(\&)') +patsubst(`GNUs not Unix', `[A-Z][a-z]+') +EOF + +cat <<\EOF >ok +OBS: GNUs not Unix +OBS: GNUs OBS: not OBS: Unix +(GNUs)() (not)() (Unix) +(GNUs) (not) (Unix) +GN not +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/patsubst.2.test b/tests/patsubst.2.test new file mode 100755 index 00000000..47ce0b77 --- /dev/null +++ b/tests/patsubst.2.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# patsubst.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3001 + +. ${srcdir}/defs + +cat <<\EOF >in +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') +EOF + +cat <<\EOF >ok +Gnus Not Unix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pseudoar.1.test b/tests/pseudoar.1.test new file mode 100755 index 00000000..060af181 --- /dev/null +++ b/tests/pseudoar.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# pseudoar.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1101 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`nargs', `$#') +nargs +nargs() +nargs(arg1, arg2, arg3) +EOF + +cat <<\EOF >ok + +0 +1 +3 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pseudoar.2.test b/tests/pseudoar.2.test new file mode 100755 index 00000000..765e73b2 --- /dev/null +++ b/tests/pseudoar.2.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# pseudoar.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1115 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$*') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pseudoar.3.test b/tests/pseudoar.3.test new file mode 100755 index 00000000..ef7bae06 --- /dev/null +++ b/tests/pseudoar.3.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# pseudoar.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1126 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo', `$@') +echo(arg1, arg2, arg3 , arg4) +EOF + +cat <<\EOF >ok + +arg1,arg2,arg3 ,arg4 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pseudoar.4.test b/tests/pseudoar.4.test new file mode 100755 index 00000000..b95fade9 --- /dev/null +++ b/tests/pseudoar.4.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# pseudoar.4.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1136 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`echo1', `$*') +define(`echo2', `$@') +define(`foo', `This is macro `foo'.') +echo1(foo) +echo2(foo) +EOF + +cat <<\EOF >ok + + + +This is macro This is macro foo.. +This is macro foo. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pseudoar.5.test b/tests/pseudoar.5.test new file mode 100755 index 00000000..c739ef51 --- /dev/null +++ b/tests/pseudoar.5.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# pseudoar.5.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1156 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `$$$ hello $$$') +foo +EOF + +cat <<\EOF >ok + +$$$ hello $$$ +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pushdef.1.test b/tests/pushdef.1.test new file mode 100755 index 00000000..fecfa31a --- /dev/null +++ b/tests/pushdef.1.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# pushdef.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1295 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +popdef(`foo') +foo +popdef(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Expansion one. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/pushdef.2.test b/tests/pushdef.2.test new file mode 100755 index 00000000..d391e5da --- /dev/null +++ b/tests/pushdef.2.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# pushdef.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1319 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Expansion one.') +foo +pushdef(`foo', `Expansion two.') +foo +define(`foo', `Second expansion two.') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok + +Expansion one. + +Expansion two. + +Second expansion two. + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/regexp.1.test b/tests/regexp.1.test new file mode 100755 index 00000000..a83a2228 --- /dev/null +++ b/tests/regexp.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# regexp.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2854 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\<[a-z]\w+') +regexp(`GNUs not Unix', `\<Q\w*') +EOF + +cat <<\EOF >ok +5 +-1 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/regexp.2.test b/tests/regexp.2.test new file mode 100755 index 00000000..6ed53dd8 --- /dev/null +++ b/tests/regexp.2.test @@ -0,0 +1,19 @@ +#!/bin/sh + +# regexp.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2866 + +. ${srcdir}/defs + +cat <<\EOF >in +regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***') +EOF + +cat <<\EOF >ok +*** Unix *** nix *** +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/run-test b/tests/run-test new file mode 100755 index 00000000..c5223163 --- /dev/null +++ b/tests/run-test @@ -0,0 +1,29 @@ +#!/bin/sh +# Run a test manually +# Copyright (C) 1998 Free Software Foundation, Inc. + +srcdir=. +export srcdir + +if sh "$@"; then + echo "Test succeeded" +else + echo "TEST FAILED" + + if cmp testSubDir/ok testSubDir/out 2>/dev/null; then + : + else + echo "stdout mosmatch" + diff -c testSubDir/ok testSubDir/out + fi + + msgerr="" + if test -e testSubDir/err; then + if cmp testSubDir/okerr testSubDir/err 2>/dev/null; then + : + else + echo "stderr mismatch" + diff -c testSubDir/okerr testSubDir/err + fi + fi +fi diff --git a/tests/stamp-TESTS b/tests/stamp-TESTS new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/stamp-TESTS diff --git a/tests/substr.1.test b/tests/substr.1.test new file mode 100755 index 00000000..ebfc000f --- /dev/null +++ b/tests/substr.1.test @@ -0,0 +1,21 @@ +#!/bin/sh + +# substr.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2892 + +. ${srcdir}/defs + +cat <<\EOF >in +substr(`gnus, gnats, and armadillos', 6) +substr(`gnus, gnats, and armadillos', 6, 5) +EOF + +cat <<\EOF >ok +gnats, and armadillos +gnats +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/sysval.1.test b/tests/sysval.1.test new file mode 100755 index 00000000..e79a0ef5 --- /dev/null +++ b/tests/sysval.1.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# sysval.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 3347 + +. ${srcdir}/defs + +cat <<\EOF >in +syscmd(`false') +ifelse(sysval, 0, zero, non-zero) +syscmd(`true') +sysval +EOF + +cat <<\EOF >ok + +non-zero + +0 +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/trace.1.test b/tests/trace.1.test new file mode 100755 index 00000000..7d103f7f --- /dev/null +++ b/tests/trace.1.test @@ -0,0 +1,33 @@ +#!/bin/sh + +# trace.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1706 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`foo', `Hello World.') +define(`echo', `$@') +traceon(`foo', `echo') +foo +echo(gnus, and gnats) +EOF + +cat <<\EOF >ok + + + +Hello World. +gnus,and gnats +EOF + +cat <<\EOF >okerr +m4trace: -1- foo -> `Hello World.' +m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' +EOF + +$M4 -d in >out 2>err +sed -e "s, ../../src/m4:, m4:," err >sederr && mv sederr err + +$CMP -s out ok && $CMP -s err okerr + diff --git a/tests/translit.1.test b/tests/translit.1.test new file mode 100755 index 00000000..51a4396a --- /dev/null +++ b/tests/translit.1.test @@ -0,0 +1,23 @@ +#!/bin/sh + +# translit.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2933 + +. ${srcdir}/defs + +cat <<\EOF >in +translit(`GNUs not Unix', `A-Z') +translit(`GNUs not Unix', `a-z', `A-Z') +translit(`GNUs not Unix', `A-Z', `z-a') +EOF + +cat <<\EOF >ok +s not nix +GNUS NOT UNIX +tmfs not fnix +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/undefine.1.test b/tests/undefine.1.test new file mode 100755 index 00000000..e2450f79 --- /dev/null +++ b/tests/undefine.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# undefine.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 1187 + +. ${srcdir}/defs + +cat <<\EOF >in +foo +define(`foo', `expansion text') +foo +undefine(`foo') +foo +EOF + +cat <<\EOF >ok +foo + +expansion text + +foo +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/undivert.1.test b/tests/undivert.1.test new file mode 100755 index 00000000..10c6625e --- /dev/null +++ b/tests/undivert.1.test @@ -0,0 +1,27 @@ +#!/bin/sh + +# undivert.1.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2632 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted. +divert +This text is not diverted. +undivert(1) +EOF + +cat <<\EOF >ok + +This text is not diverted. + +This text is diverted. + +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/undivert.2.test b/tests/undivert.2.test new file mode 100755 index 00000000..d49f7fc4 --- /dev/null +++ b/tests/undivert.2.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# undivert.2.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2656 + +. ${srcdir}/defs + +cat <<\EOF >in +divert(1) +This text is diverted first. +divert(0)undivert(1)dnl +undivert(1) +divert(1) +This text is also diverted but not appended. +divert(0)undivert(1)dnl +EOF + +cat <<\EOF >ok + +This text is diverted first. + + +This text is also diverted but not appended. +EOF + +$M4 -d in >out + +$CMP -s out ok + diff --git a/tests/undivert.3.test b/tests/undivert.3.test new file mode 100755 index 00000000..146374d9 --- /dev/null +++ b/tests/undivert.3.test @@ -0,0 +1,25 @@ +#!/bin/sh + +# undivert.3.test is part of the GNU m4 testsuite +# generated from example in ../doc/m4.texinfo line 2682 + +. ${srcdir}/defs + +cat <<\EOF >in +define(`bar', `BAR') +undivert(`foo') +include(`foo') +EOF + +cat <<\EOF >ok + +bar + +BAR + +EOF + +M4PATH=$srcdir $M4 -d in >out + +$CMP -s out ok + |