From 77ca3ebf306b98038d5e6e0372ee86ce16530954 Mon Sep 17 00:00:00 2001 From: Jeroen Ruigrok/asmodai Date: Thu, 21 Apr 2005 18:16:32 +0000 Subject: [PATCH 1/1] Add gperf 3.0.1. Submitted by: Andreas Hauser --- contrib/gperf-3.0.1/AUTHORS | 2 + contrib/gperf-3.0.1/COPYING | 340 ++ contrib/gperf-3.0.1/ChangeLog | 3185 ++++++++++++++++ contrib/gperf-3.0.1/INSTALL | 183 + contrib/gperf-3.0.1/Makefile.devel | 44 + contrib/gperf-3.0.1/NEWS | 80 + contrib/gperf-3.0.1/README | 28 + contrib/gperf-3.0.1/README.DELETED | 24 + contrib/gperf-3.0.1/doc/gperf.1 | 212 ++ contrib/gperf-3.0.1/doc/gperf.texi | 1356 +++++++ contrib/gperf-3.0.1/doc/gpl.texinfo | 398 ++ contrib/gperf-3.0.1/lib/getline.cc | 118 + contrib/gperf-3.0.1/lib/getline.h | 40 + contrib/gperf-3.0.1/lib/getopt.c | 1042 ++++++ contrib/gperf-3.0.1/lib/getopt.c.patch | 25 + contrib/gperf-3.0.1/lib/getopt.h | 138 + contrib/gperf-3.0.1/lib/getopt.h.patch | 70 + contrib/gperf-3.0.1/lib/getopt1.c | 188 + contrib/gperf-3.0.1/lib/hash.cc | 27 + contrib/gperf-3.0.1/lib/hash.h | 15 + contrib/gperf-3.0.1/src/bool-array.cc | 47 + contrib/gperf-3.0.1/src/bool-array.h | 79 + contrib/gperf-3.0.1/src/bool-array.icc | 78 + contrib/gperf-3.0.1/src/config.h.in | 20 + contrib/gperf-3.0.1/src/config.h.msvc | 20 + contrib/gperf-3.0.1/src/config.h_vms | 20 + contrib/gperf-3.0.1/src/configure | 4190 ++++++++++++++++++++++ contrib/gperf-3.0.1/src/configure.in | 67 + contrib/gperf-3.0.1/src/hash-table.cc | 167 + contrib/gperf-3.0.1/src/hash-table.h | 66 + contrib/gperf-3.0.1/src/input.cc | 1000 ++++++ contrib/gperf-3.0.1/src/input.h | 69 + contrib/gperf-3.0.1/src/keyword-list.cc | 175 + contrib/gperf-3.0.1/src/keyword-list.h | 85 + contrib/gperf-3.0.1/src/keyword-list.icc | 53 + contrib/gperf-3.0.1/src/keyword.cc | 161 + contrib/gperf-3.0.1/src/keyword.h | 116 + contrib/gperf-3.0.1/src/keyword.icc | 42 + contrib/gperf-3.0.1/src/main.cc | 155 + contrib/gperf-3.0.1/src/options.cc | 1050 ++++++ contrib/gperf-3.0.1/src/options.h | 289 ++ contrib/gperf-3.0.1/src/options.icc | 150 + contrib/gperf-3.0.1/src/output.cc | 2082 +++++++++++ contrib/gperf-3.0.1/src/output.h | 154 + contrib/gperf-3.0.1/src/positions.cc | 177 + contrib/gperf-3.0.1/src/positions.h | 171 + contrib/gperf-3.0.1/src/positions.icc | 285 ++ contrib/gperf-3.0.1/src/search.cc | 1684 +++++++++ contrib/gperf-3.0.1/src/search.h | 165 + contrib/gperf-3.0.1/src/version.cc | 28 + contrib/gperf-3.0.1/src/version.h | 25 + 51 files changed, 20385 insertions(+) create mode 100644 contrib/gperf-3.0.1/AUTHORS create mode 100644 contrib/gperf-3.0.1/COPYING create mode 100644 contrib/gperf-3.0.1/ChangeLog create mode 100644 contrib/gperf-3.0.1/INSTALL create mode 100644 contrib/gperf-3.0.1/Makefile.devel create mode 100644 contrib/gperf-3.0.1/NEWS create mode 100644 contrib/gperf-3.0.1/README create mode 100644 contrib/gperf-3.0.1/README.DELETED create mode 100644 contrib/gperf-3.0.1/doc/gperf.1 create mode 100644 contrib/gperf-3.0.1/doc/gperf.texi create mode 100644 contrib/gperf-3.0.1/doc/gpl.texinfo create mode 100644 contrib/gperf-3.0.1/lib/getline.cc create mode 100644 contrib/gperf-3.0.1/lib/getline.h create mode 100644 contrib/gperf-3.0.1/lib/getopt.c create mode 100644 contrib/gperf-3.0.1/lib/getopt.c.patch create mode 100644 contrib/gperf-3.0.1/lib/getopt.h create mode 100644 contrib/gperf-3.0.1/lib/getopt.h.patch create mode 100644 contrib/gperf-3.0.1/lib/getopt1.c create mode 100644 contrib/gperf-3.0.1/lib/hash.cc create mode 100644 contrib/gperf-3.0.1/lib/hash.h create mode 100644 contrib/gperf-3.0.1/src/bool-array.cc create mode 100644 contrib/gperf-3.0.1/src/bool-array.h create mode 100644 contrib/gperf-3.0.1/src/bool-array.icc create mode 100644 contrib/gperf-3.0.1/src/config.h.in create mode 100644 contrib/gperf-3.0.1/src/config.h.msvc create mode 100644 contrib/gperf-3.0.1/src/config.h_vms create mode 100644 contrib/gperf-3.0.1/src/configure create mode 100644 contrib/gperf-3.0.1/src/configure.in create mode 100644 contrib/gperf-3.0.1/src/hash-table.cc create mode 100644 contrib/gperf-3.0.1/src/hash-table.h create mode 100644 contrib/gperf-3.0.1/src/input.cc create mode 100644 contrib/gperf-3.0.1/src/input.h create mode 100644 contrib/gperf-3.0.1/src/keyword-list.cc create mode 100644 contrib/gperf-3.0.1/src/keyword-list.h create mode 100644 contrib/gperf-3.0.1/src/keyword-list.icc create mode 100644 contrib/gperf-3.0.1/src/keyword.cc create mode 100644 contrib/gperf-3.0.1/src/keyword.h create mode 100644 contrib/gperf-3.0.1/src/keyword.icc create mode 100644 contrib/gperf-3.0.1/src/main.cc create mode 100644 contrib/gperf-3.0.1/src/options.cc create mode 100644 contrib/gperf-3.0.1/src/options.h create mode 100644 contrib/gperf-3.0.1/src/options.icc create mode 100644 contrib/gperf-3.0.1/src/output.cc create mode 100644 contrib/gperf-3.0.1/src/output.h create mode 100644 contrib/gperf-3.0.1/src/positions.cc create mode 100644 contrib/gperf-3.0.1/src/positions.h create mode 100644 contrib/gperf-3.0.1/src/positions.icc create mode 100644 contrib/gperf-3.0.1/src/search.cc create mode 100644 contrib/gperf-3.0.1/src/search.h create mode 100644 contrib/gperf-3.0.1/src/version.cc create mode 100644 contrib/gperf-3.0.1/src/version.h diff --git a/contrib/gperf-3.0.1/AUTHORS b/contrib/gperf-3.0.1/AUTHORS new file mode 100644 index 0000000000..184c7ce67c --- /dev/null +++ b/contrib/gperf-3.0.1/AUTHORS @@ -0,0 +1,2 @@ +Douglas C. Schmidt +Bruno Haible diff --git a/contrib/gperf-3.0.1/COPYING b/contrib/gperf-3.0.1/COPYING new file mode 100644 index 0000000000..bab08afad3 --- /dev/null +++ b/contrib/gperf-3.0.1/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, + 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. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/contrib/gperf-3.0.1/ChangeLog b/contrib/gperf-3.0.1/ChangeLog new file mode 100644 index 0000000000..1af586c40d --- /dev/null +++ b/contrib/gperf-3.0.1/ChangeLog @@ -0,0 +1,3185 @@ +2003-06-12 Bruno Haible + + * gperf-3.0.1 released. + + * src/version.cc: Bump version number to 3.0.1. + * doc/gperf.texi: Likewise. + * tests/c-parse.exp, tests/charsets.exp, tests/chill.exp, + tests/cplusplus.exp, tests/gpc.exp, tests/incomplete.exp, + tests/java.exp, tests/languages.exp, tests/modula2.exp, + tests/objc.exp, tests/permut2.exp, tests/permut3.exp, + tests/permutc2.exp, tests/test-4.exp: Update. + +2003-05-31 Bruno Haible + + * doc/gperf.texi (User-supplied Struct): Mention the possibility of an + abbreviated struct declaration. + * src/input.cc (Input::read_input): Support struct declarations of the + form "struct foo;". + * tests/incomplete.gperf: New file. + * tests/incomplete.exp: New file. + * tests/Makefile.in (check-test): Check incomplete.gperf too. + Reported by Rob Leslie . + +2003-05-20 Bruno Haible + + * doc/Makefile.in (gperf.ps): Don't use $< in a target rule. + +2003-05-27 Bruno Haible + + * Makefile.vms (CC): Correct value. + (getopt.obj, getopt1.obj, getline.obj, hash.obj): Don't set + HAVE_CONFIG_H. + +2003-05-17 Bruno Haible + + * Makefile.msvc (DEBUGFLAGS): New variable. + (gperf.exe): Use it, and MFLAGS too. + +2003-05-08 Bruno Haible + + * gperf-3.0 released. + +2003-05-07 Bruno Haible + + * src/version.cc: Bump version number to 3.0. + * doc/gperf.texi: Likewise. + * tests/c-parse.exp, tests/charsets.exp, tests/chill.exp, + tests/cplusplus.exp, tests/gpc.exp, tests/java.exp, + tests/languages.exp, tests/modula2.exp, tests/objc.exp, + tests/permut2.exp, tests/permut3.exp, tests/permutc2.exp, + tests/test-4.exp: Update. + + * src/configure.in: Fix AC_INIT argument. + + * Makefile.devel (configure, lib/configure, src/configure, + tests/configure, doc/configure): Use the newest autoconf. + (src/config.h.in): Use the newest autoheader. + +2003-05-03 Bruno Haible + + * doc/gperf.texi: Use two spaces as sentence separator, as recommended + by the texinfo manual. + +2003-04-12 Bruno Haible + + * doc/configure.in (mandir): Change default value. + * doc/Makefile.in (docdir): Use datadir instead of prefix. + * Makefile.msvc (datadir): New variable. + (mandir, docdir): Use it instead of prefix. + (install, installdirs): Update. + * Makefile.vms (datadir): New variable. + (mandir, docdir): Use it instead of prefix. + (install, installdirs): Update. + +2003-04-12 Bruno Haible + + * README.vms: New file. + * Makefile.vms: New file. + * Makefile.devel (src/config.h_vms): New rule. + (all): Depend on it. + +2003-03-19 Bruno Haible + + * src/input.cc (Input::read_input): Ignore comments at the beginning + of the declarations section. + * doc/gperf.texi (Controls for GNU indent): New section. + Reported by Bruce Lilly . + +2003-03-19 Bruno Haible + + * src/output.cc (Output::output_hash_function): Avoid lint warning if + not all arguments of the hash function are used. Avoid lint warning + for fallthrough in switch. + * tests/c-parse.exp, tests/charsets.exp, tests/chill.exp, + tests/cplusplus.exp, tests/java.exp, tests/languages.exp, + tests/modula2.exp, tests/objc.exp: All /*FALLTHROUGH*/ to expected + output. + Reported by Bruce Lilly . + +2003-03-01 Bruno Haible + + * src/options.h (Options::set_initializer_suffix): New declaration. + * src/options.cc (Options::set_initializer_suffix): New method. + * src/input.cc (Input::read_input): Recognize %define + initializer-suffix. + * doc/gperf.texi (Gperf Declarations): Document %define + initializer-suffix. + * NEWS: Update. + +2003-02-26 Bruno Haible + + * Makefile.msvc: New file. + * README.woe32: New file. + * Makefile.devel (all): Depend on src/config.h.msvc. + (src/config.h.msvc): New rule. + +2003-01-07 Bruno Haible + + * src/input.h (Input::_charset_dependent): New field. + * src/input.cc (Input::read_input): Also set _charset_dependent. + * src/main.cc (main): Pass _charset_dependent from Input to Output. + * src/output.h (Output::Output): Add charset_dependent argument. + (Output::_charset_dependent): New field. + * src/output.cc (Output::Output): Add charset_dependent argument. + (Output::output): Provoke a compilation error if the execution + character set doesn't match the expectations. + * tests/c-parse.exp, tests/charsets.exp, tests/chill.exp, + tests/cplusplus.exp, tests/gpc.exp, tests/java.exp, + tests/languages.exp, tests/modula2.exp, tests/objc.exp, + tests/permut2.exp, tests/permut3.exp, tests/permutc2.exp, + tests/test-4.exp: Update. + + * src/options.cc (Options::long_usage): Change bug report address to + . + * tests/test-6.exp: Update. + + * src/output.cc (USE_DOWNCASE_TABLE): New macro. + (output_upperlower_table): New function. + (output_upperlower_strcmp, output_upperlower_strncmp, + output_upperlower_memcmp): Emit gperf_downcase array accesses. + (Output::output): Call output_upperlower_table. + * tests/permutc2.exp: Update. + + * src/keyword-list.icc (KeywordExt_List::rest): Use a portable cast. + (Only in GCC a cast of an lvalue is an lvalue.) + +2003-01-01 Bruno Haible + + * src/options.cc (Options::parse_options): Update copyright year. + + * doc/gperf.texi (@author): Add me. + + * src/options.h (NULLSTRINGS): New enum value. + (Options::get_stringpool_name, Options::set_stringpool_name): New + method declarations. + (Options::_stringpool_name): New field. + * src/options.icc (Options::get_stringpool_name): New method. + * src/options.cc (DEFAULT_STRINGPOOL_NAME): New variable. + (Options::long_usage): Document -Q and --null-strings. + (Options::Options): Initialize _stringpool_name. + (Options::~Options): Output _stringpool_name, NULLSTRINGS values too. + (Options::set_stringpool_name): New method. + (long_options): Add options --string-pool-name, --null-strings. + (Options::parse_options): Implement options -P, -Q and --null-strings. + * src/input.cc (Input::read_input): Recognize declarations %pic, + %define string-pool-name, %null-strings. + * src/output.h (Output::output_string_pool, + Output::output_lookup_pools): New method declarations. + (Output::_wordlist_eltype): New field. + * src/output.cc (Output::output_keylength_table): Trivial + simplification. + (Output::output_string_pool): New method. + (output_keyword_entry): Add stringpool_index argument. For SHAREDLIB, + use struct offsets. + (output_keyword_blank_entries): For SHAREDLIB, use -1 instead of "". + (Output::output_keyword_table): Use _wordlist_eltype instead of + _struct_tag. Compute stringpool_index for output_keyword_entry. + (Output::output_lookup_pools): New method. + (Output::output_lookup_function_body): Use _wordlist_eltype instead of + _struct_tag. For SHAREDLIB, use "+ stringpool" to convert offsets to + strings. Use "o >= 0" to test for nonempty table entry. + (Output::output_lookup_function): Call output_lookup_pools. + (Output::output): Initialize _wordlist_eltype. Call + output_lookup_pools. + * tests/jstest4.gperf: New file. + * tests/test-6.exp: Update. + * tests/Makefile.in (check-lang-syntax): Drop test of -p. Add tests of + -P and -Q. + * doc/gperf.texi (User-supplied Struct): Mention that first field has + to be of type 'int' if -P is given. + (Gperf Declarations): Document %pic, %define string-pool-name, + %null-strings. + (Output Details): Update description of option -P. Document options -Q + and --null-strings. + + * tests/Makefile.in (check-link-c, check-ada, check-pascal, + check-test): Omit option -p. + * tests/c-parse.exp: Regenerated. + * tests/chill.exp: Regenerated. + * tests/cplusplus.exp: Regenerated. + * tests/gpc.exp: Regenerated. + * tests/java.exp: Regenerated. + * tests/objc.exp: Regenerated. + * tests/test-4.exp: Regenerated. + + * src/output.cc (Output::output_lookup_function_body): Omit the + multicompare code section and its variables when it is not used. + * tests/chill.exp: Regenerated. + + * src/output.c (Output_Compare::output_firstchar_comparison): New + method. + (Output_Compare_Strcmp::output_comparison, + Output_Compare_Strncmp::output_comparison, + Output_Compare_Memcmp::output_comparison): Use it. + * tests/permutc2.exp: Update. + + * tests/smtp.gperf: New file, based on a contribution by Bruce Lilly. + * tests/Makefile.in (check-smtp): New rule. + (check): Depend on it. + (clean): Update. + +2002-12-12 Bruno Haible + + * src/search.h (Search::init_selchars_tuple, + Search::count_duplicates_tuple): Add alpha_unify argument. + (Search::count_duplicates_tuple): New method declaration. + * src/search.cc (Search::init_selchars_tuple, + Search::count_duplicates_tuple): Add alpha_unify argument. + (Search::find_positions): Update. + (Search::count_duplicates_tuple): New method. + (Search::count_duplicates_multiset): Free temp alpha_unify vector. + (Search::find_alpha_inc): Call count_duplicates_tuple. + + * src/configure.in: Add test for stack-allocated variable-size arrays. + * src/config.h.in: Regenerated. + * src/search.cc: Include config.h. + (DYNAMIC_ARRAY, FREE_DYNAMIC_ARRAY): New macros. + (Search::find_alpha_inc, Search::count_possible_collisions, + Search::find_asso_values): Use them. + * src/Makefile.in (search.o): Depend on config.h. + + * src/search.h (Search::keyword_list_length, Search::max_key_length, + Search::get_max_keysig_size, Search::prepare): Remove declarations. + (Search::prepare): Renamed from Search::preprepare. + (Search::_max_selchars_length): New field. + * src/search.cc (Search::prepare): Renamed from Search::preprepare. + (Search::prepare_asso_values): Merged with old Search::prepare. + Initialize _max_selchars_length. + (Search::keyword_list_length): Remove function. Use _list_len instead. + (Search::max_key_length): Remove function. Use _max_key_len instead. + (Search::get_max_keysig_size): Remove function. Use + _max_selchars_length instead. + (Search::count_possible_collisions, Search::find_asso_values): Update. + (Search::find_good_asso_values): Call just prepare_asso_values. + (Search::~Search): Update. + + * src/output.h (Output::output_asso_values_ref): New declaration. + * src/output.cc (char_to_index): Remove variable. + (Output::output_asso_values_ref): New function. + (Output::output_hash_function): Use it. + (Output::output): Update. + + * src/positions.h (Positions::is_useall, Positions::set_useall, + Positions::iterator, Positions::reviterator): New method declarations. + (Positions::_useall): New field. + (PositionIterator): Make constructor private. Add a constructor and a + copy constructor. + (PositionIterator::remaining): New declaration. + (PositionReverseIterator): Make constructor private. Add a constructor + and a copy constructor. + (PositionReverseIterator::remaining): New declaration. + (PositionReverseIterator::_minindex): New field. + * src/positions.icc (Positions::Positions): Initialize _useall. + (Positions::operator=): Likewise. + (Positions::is_useall, Positions::set_useall): New methods. + (Positions::sort): Do nothing if _useall is set. + (Positions::iterator, Positions::reviterator): New methods. + (PositionIterator::PositionIterator): New constructor. + (PositionIterator::remaining): New method. + (PositionReverseIterator::PositionReverseIterator): New constructor. + (PositionReverseIterator::next): Use _minindex as bound. + (PositionReverseIterator::remaining): New method. + * src/positions.cc (Positions::add, Positions::remove): Reset the + useall flag. + (Positions::print): Handle the useall case. + * src/options.h (ALLCHARS): Remove. + * src/options.cc (Options::~Options): Update. + (Options::parse_options): Use Positions::set_useall(). + * src/keyword.h (KeywordExt::init_selchars_tuple, + KeywordExt::init_selchars_multiset, KeywordExt::init_selchars_low): + Remove use_all_chars argument. + * src/keyword.cc (KeywordExt::init_selchars_low): Remove use_all_chars + argument. Tell the position iterator to stop at _allchars_length. + Remove special case code for -k'*'. + (KeywordExt::init_selchars_tuple, KeywordExt::init_selchars_multiset): + Remove use_all_chars argument. + * src/search.h (Search::init_selchars_tuple): Remove use_all_chars + argument. + (Search::init_selchars_multiset): Likewise. + * src/search.cc (Search::init_selchars_tuple): Remove use_all_chars + argument. + (Search::count_duplicates_tuple, Search::find_positions): Update. + (Search::compute_alpha_unify): Remove special case code for -k'*'. + (Search::init_selchars_multiset): Remove use_all_chars argument. + (Search::count_duplicates_multiset): Update. + (Search::find_alpha_inc): Remove special case code for -k'*'. + (Search::prepare): Update. + (Search::get_max_keysig_size): Update. + * src/output.cc (Output::output_hash_function): Remove special case + code for -k'*'. + * tests/chill.exp: Regenerated. + +2002-12-11 Bruno Haible + + Change the positions to be 0-based, instead of 1-based. + * src/positions.h (Positions::LASTCHAR): Set to -1. + (Positions::MAX_SIZE): New constant. + (Positions::pointer): Change return type. + (Positions::_positions): Change element type. + (PositionIterator::EOS, PositionReverseIterator::EOS): Set to -2. + * src/positions.icc (Positions::pointer): Change return type. + (Positions::sort): Update. + * src/positions.cc (Positions::contains, Positions::add, + Positions::remove): Update. + (Positions::print): Update. Fix off-by-one bug. + * src/options.cc (Options::~Options): Update. + (Options::parse_options): Set BAD_VALUE to -3. Update. + * src/keyword.cc (KeywordExt::init_selchars_low): Update. + * src/search.cc (Search::find_positions, Search::compute_alpha_unify, + Search::find_alpha_inc): Update. + * src/output.cc (Output::output_hash_function): Update. Don't emit + a 'case' statement right after 'default:'. + * tests/c-parse.exp: Regenerated. + * tests/charsets.exp: Regenerated. + * tests/cplusplus.exp: Regenerated. + * tests/java.exp: Regenerated. + * tests/languages.exp: Regenerated. + * tests/modula2.exp: Regenerated. + * tests/objc.exp: Regenerated. + +2002-12-10 Bruno Haible + + * src/options.h: Reorder enum values. + (Options::short_usage, Options::long_usage): Make static. + * src/options.cc (Options::short_usage); No longer print a monster + usage line. + (Options::print_options): Improve output of options like + --key-positions=1,2,$. + (Options::~Options): Update. + + * src/options.h (UPPERLOWER): New enum value. + * src/options.cc (Options::long_usage): Document option --ignore-case. + (Options::~Options): Update. + (long_options): Add option --ignore-case. + (Options::parse_options): Handle option --ignore-case. + * src/input.cc (Input::read_input): Recognize option %ignore-case. + * src/keyword.h (KeywordExt::init_selchars_tuple, + KeywordExt::init_selchars_multiset, KeywordExt::init_selchars_low): + Add alpha_unify argument. + * src/keyword.cc (KeywordExt::init_selchars_low): Add alpha_unify + argument. + (KeywordExt::init_selchars_tuple): Add alpha_unify argument. + (KeywordExt::init_selchars_multiset): Add alpha_unify argument. + * src/search.h (Search::compute_alpha_size, + Search::compute_alpha_unify): New declarations. + (Search::init_selchars_multiset): Add alpha_unify argument. + (Search::_alpha_unify): New field. + * src/search.cc (Search::compute_alpha_size, + Search::compute_alpha_unify): New functions. + (Search::init_selchars_tuple): Update. + (Search::find_positions): Temporarily set _alpha_unify. Perform a + case insensitive comparison if needed. + (Search::init_selchars_multiset): Add alpha_unify argument. + (Search::count_duplicates_multiset): Call compute_alpha_unify. + (Search::find_alpha_inc): Temporarily set _alpha_unify. At the end, + set _alpha_size and _alpha_unify. + (Search::prepare): Update. Don't compute _alpga_size here. + (Search::optimize): Propagate unified asso_values. + (Search::~Search) Delete _alpha_unify. + * src/output.cc (output_upperlower_strcmp, output_upperlower_strncmp, + output_upperlower_memcmp): New functions. + (Output_Compare_Strcmp::output_comparison, + Output_Compare_Strncmp::output_comparison, + Output_Compare_Memcmp::output_comparison): Use the case-insensitive + comparison function if --ignore-case was given. + (Output::output): Emit the auxiliary case-insensitive comparison + function if needed. + * tests/permutc2.gperf, tests/permutc2.exp: New files. + * tests/Makefile.in (check-test): Also check permutc2.gperf. + * tests/test-6.exp: Update. + * doc/gperf.texi (Gperf Declarations): Document %ignore-case. + (Input Details): Document option --ignore-case. + * NEWS: Update. + + * src/search.cc (Search::optimize): Fill unused asso_values[] entries + with a large value. + * src/output.h (Output::Output): Remove occurrences argument. + (Output::_occurrences): Remove field. + * src/output.cc (Output::Output): Remove occurrences argument. + (Output::output_hash_function): Ignore _occurrences. + * src/main.cc (main): Don't pass the _occurrences to Output. + + * src/search.cc (Search::preprepare): Exit if keywords contain + out-of-range characters. + + * src/search.cc (for): Define so as to avoid errors with old compilers. + + * src/options.h (SHAREDLIB): New enum value. + * src/options.cc (Options::short_usage): Mention option -P. + (Options::long_usage): Document option -P. + (long_options): Add option --pic. + (Options::parse_options): Handle option -P/--pic. + * src/output.cc (output_keyword_blank_entries): When SHAREDLIB is + specified, emit NULL pointers instead of "". + (Output::output_lookup_function_body): When SHAREDLIB is specified + and SWITCH and DUP and not specified, test the table entry against + NULL before the string comparison. + * tests/test-6.exp: Update. + * doc/gperf.texi (Output Details): Document option -P. + * NEWS: Update. + Suggested by Ulrich Drepper. + +2002-12-08 Bruno Haible + + * tests/permut2.gperf, tests/permut2.exp: New files. + * tests/permut3.gperf, tests/permut3.exp: New files. + * tests/charsets.gperf: New file, from Bruce Lilly. + * tests/charsets.exp: New file. + * tests/languages.gperf: New file, from Bruce Lilly. + * tests/languages.exp: New file. + * Makefile.in (check-test): Test them all. + + Completely new asso_values search algorithm. + * src/search.h (Search::compute_occurrence, Search::clear_determined, + Search::set_determined, Search::already_determined, Search::reorder): + Remove functions. + (Search::init_asso_values, Search::sort_by_occurrence, + Search::compute_occurrence, Search::sort_by_occurrence, + Search::has_collisions, Search::collision_prior_to): Remove functions. + (Search::compute_partition, Search::count_possible_collisions, + Search::unchanged_partition): New method declarations. + (Search::_determined): Remove field. + * src/search.cc (Search::prepare): Don't initialize _determined. + (Search::compute_occurrence, greater_by_occurrence, + Search::clear_determined, Search::set_determined, + Search::already_determined, Search::reorder): Remove functions. + (Search::init_asso_values, compute_disjoint_union, + Search::sort_by_occurrence, Search::compute_occurrence, + Search::sort_by_occurrence, Search::has_collisions, + Search::collision_prior_to): Remove functions. + (StackEntry): Remove class. + (EquivalenceClass, Step): New classes. + (equals, Search::compute_partition, delete_partition, + Search::count_possible_collisions, Search::unchanged_partition): New + functions. + (Search::find_asso_values): Completely rewritten. + (Search::find_good_asso_values): Don't call reorder(). + (Search::~Search): Don't free _determined. + * src/keyword.h (KeywordExt::_occurrence): Remove field. + * src/options.h (ORDER, FAST, OPT_CHOICE): Remove enum values. + (Options::_iterations): Remove field. + * src/options.icc (Options::get_iterations): Remove method. + * src/options.cc (Options::long_usage): Remove mention of -f and -o. + (Options::Options): Don't initialize _iterations. + (Options::~Options): Update. + (Options::parse_options): Do nothing for options -f, -o, -O. + * doc/gperf.texi: (Contributors): Update. + (Algorithmic Details): Remove options -f and -o. Update description + of option -s. + * tests/c-parse.exp, tests/chill.exp, tests/cplusplus.exp, + tests/gpc.exp, tests/java.exp, tests/modula2.exp, tests/objc.exp, + tests/test-4.exp): Regenerated, smaller than before. + * tests/test-6.exp: Update. + * NEWS: Update. + +2002-12-08 Bruno Haible + + * src/search.h (Search::_alpha_size): Change type to 'unsigned int'. + (Search::_asso_value_max): Likewise. + * src/search.cc (Search::prepare_asso_values): Update. + (Search::init_asso_values): Update. + (Search::~Search): Update. + * src/output.h (Output::Output): Change alpha_size type to + 'unsigned int'. + (Output::_alpha_size): Change type to 'unsigned int'. + * src/output.cc (Output::Output): Change alpha_size type to + 'unsigned int'. + (Output::output_hash_function): Update. + +2002-12-07 Bruno Haible + + * src/options.h (OPT_CHOICE): New enum value. + * src/options.cc (Options::~Options): Update. + (long_options): New option --optimized-collision-resolution. + (Options::parse_options): Accept option -O. + * src/search.h (Search::sort_by_occurrence): Change argument to + 'unsigned int'. + (Search::compute_occurrence, Search::sort_by_occurrence): New method + declarations. + * src/search.cc (Search::sort_by_occurrence): Change argument to + 'unsigned int'. + (Search::compute_occurrence, Search::sort_by_occurrence): New methods. + (Search::find_asso_values): Implement OPT_CHOICE. More debugging + output. + + * src/search.cc (Search::prepare_asso_values) [DEBUG]: Also print + the keyword list in order. + (Search::find_asso_values) [DEBUG]: Upon failure, print the union_set. + + * src/options.h (Options::get_size_multiple): Change return type to + float. + (Options::_size_multiple): Change type to float. + * src/options.icc (Options::get_size_multiple): Change return type to + float. + * src/options.cc (Options::long_usage): Update description of option + -s. + (Options::~Options): Update. + (Options::parse_options): For option -s, accept a fraction. + * src/search.cc (Search::prepare_asso_values): Use get_size_multiple + as it is. + * tests/test-6.exp: Update. + * doc/gperf.texi (Algorithmic Details): Update description of option + -s. + +2002-12-04 Bruno Haible + + Improve debugging output. + * src/hash-table.h (Hash_Table::dump): New method. + * src/hash-table.cc (Hash_Table::dump): New method, extracted from + destructor. + (Hash_Table::~Hash_Table): No longer print the contents. + * src/positions.h (PositionReverseIterator): New class. + * src/positions.icc (PositionReverseIterator::PositionReverseIterator, + PositionReverseIterator::next): New methods. + * src/search.cc (Search::find_positions): If debugging, print the + result. + (Search::find_alpha_inc): If debugging, print the result. + (Search::prepare): Explicitly dump the hash table's contents here. + + Portability fixes. + * src/positions.h (Positions::LASTCHAR, Positions::MAX_KEY_POS, + PositionIterator::EOS): Define as compile-time constants using enum. + * src/bool-array.cc (Bool_Array::~Bool_Array): Remove const qualifier + of pointer to be deleted. + * src/input.cc (Input::~Input): Likewise. + * src/keyword.cc (KeywordExt::delete_selchars): Likewise. + * src/main.cc (main): Likewise. + * src/hash-table.cc (Hash_Table::~Hash_Table): Limit scope of 'for' + variables. + * src/search.cc (Search::prepare_asso_values): Use a static_cast to + convert from time_t to long. This is possible because ISO C 99 says + time_t is a numeric type. + +2002-11-20 Bruno Haible + + * src/search.cc (Search::find_asso_values): Avoid gcc warnings about + uninitialized variables. + + Implement backtracking. + * src/search.h (Search::has_collisions): Renamed from + Search::less_collisions. Return a boolean. + * src/search.cc (Search::has_collisions): Renamed from + Search::less_collisions. Return a boolean. + (StackEntry): Remove field _collisions_so_far. + (Search::find_asso_values): Backtrack when encountering an unresolved + collision. Assume collisions_so_far is always zero. + (Search::optimize): Exit if there are accidental duplicates at the end. + * src/output.cc (Output::num_hash_values): Simply return the list + length. + (Output::output_keylength_table): Remove handling of accidental + duplicates. + (Output::output_keyword_table, Output::output_lookup_array): Likewise. + (output_switch_case, output_switches): Likewise. + * doc/gperf.texi (Algorithmic Details): Adjust description of options + -D, -f, -o, -r. + (Bugs): Remove note about missing backtracking. + (Projects): Likewise. + +2002-11-19 Bruno Haible + + Prepare for backtracking. + * src/search.h (Search::try_asso_value, Search::change_some_asso_value): + Remove declarations. + (Search::less_collisions, Search::collision_prior_to): New declarations. + (Search::_fewest_collisions, Search::_union_set, Search::_num_done): + Remove fields. + * src/search.cc (Search::prepare_asso_values): Don't initialize + _union_set. + (Search::try_asso_value, Search::change_some_asso_value): Remove + methods. + (Search::less_collisions, Search::collision_prior_to): New methods. + (StackEntry): New class. + (Search::find_asso_values): Reorganized to use pseudo-recursion. + (Search::~Search): Don't free _union_set. + + * src/search.h (Search::find_good_asso_values): New declaration. + * src/search.cc: Add comments about the basic structure of the + algorithm. + (Search::find_positions): Move the option[POSITIONS] test to here. + (Search::find_good_asso_values): New method, extracted from + Search::optimize. + (Search::optimize): Remove option[POSITIONS] test. Call + find_good_asso_values. + +2002-11-17 Bruno Haible + + * src/options.cc (Options::parse_options): Include copyright notice + and authors in --version output. + + Avoid artificial duplicates. + * src/keyword.h (KeywordExt::init_selchars_tuple): New declaration. + (KeywordExt::init_selchars_multiset): Renamed from + KeywordExt::init_selchars. + (KeywordExt::init_selchars_low): New declaration. + * src/keyword.cc (KeywordExt::init_selchars_low): Renamed from + KeywordExt::init_selchars. Add alpha_inc argument. Remove sorting. + (KeywordExt::init_selchars_tuple): New method. + (KeywordExt::init_selchars_multiset): New method, replaces + KeywordExt::init_selchars. + * src/search.h (Search::init_selchars_tuple): Renamed from + Search::init_selchars. + (Search::count_duplicates_tuple): Renamed from Search::count_duplicates. + (Search::init_selchars_multiset, Search::count_duplicates_multiset, + Search::find_alpha_inc): New declarations. + (Search::_alpha_inc): New field. + (Search::_alpha_size, Search::_occurrences, Search::_asso_values, + Search::_determined): Make non-const. + * src/search.cc (Search::Search): Don't initialize _key_positions, + _alpha_size, _occurrences, _asso_values, _determined here. + (Search::init_selchars_tuple): Renamed from Search::init_selchars. + (Search::count_duplicates_tuple): Renamed from Search::count_duplicates. + (Search::find_positions): Update. + (Search::init_selchars_multiset, Search::count_duplicates_multiset, + Search::find_alpha_inc): New methods. + (Search::prepare): Move preprepare, find_positions calls away. + Initialize _alpha_size, _occurrences, _asso_values, _determined here. + (Search::optimize): Call preprepare, find_positions here. Initialize + _key_positions here. + (Search::~Search): Deallocate _alpha_inc. + * src/output.cc (Output::Output): Add alpha_inc argument. + (Output::output_hash_function): Use _alpha_inc. + * src/output.h (Output::Output): Add alpha_inc argument. + (Output::_alpha_inc): New field. + * src/main.cc (main): Pass _alpha_inc from Search to Output. + * tests/chill.exp: Update. + * doc/gperf.texi (Algorithmic Details): Remove description of + artificial duplicates. + + * src/keyword.h (KeywordExt::_selchars): Change type to + 'const unsigned int *'. + * src/keyword.cc (sort_char_set): Change argument type to + 'unsigned int *'. + (KeywordExt::init_selchars): Update. + * src/search.h (Search::sort_by_occurrence): Change argument type to + 'unsigned int *'. + (Search::try_asso_value): Change argument type to 'unsigned int'. + (Search::_union_set): Change type to 'unsigned int *'. + * src/search.cc (Search::prepare, Search::compute_occurrence, + Search::set_determined, Search::already_determined, + Search::prepare_asso_values, Search::compute_hash): Update. + (compute_disjoint_union): Change argument types to 'unsigned int *'. + (Search::sort_by_occurrence): Likewise. + (Search::try_asso_value): Change argument type to 'unsigned int'. + (Search::change_some_asso_value, Search::~Search): Update. + * src/hash-table.cc (Hash_Table::~Hash_Table, Hash_Table::equal, + Hash_Table::insert): Update. + + * src/positions.h: New file, extracted from options.h. + * src/positions.icc: New file, extracted from options.icc. + * src/positions.cc: New file, extracted from options.cc. + * src/options.h: Include positions.h. Move classes Positions and + PositionsIterator away. + * src/options.icc: Move classes Positions and PositionsIterator away. + * src/options.cc: Move class Positions away. + * src/keyword.cc: Include positions.h instead of options.h. + * src/output.h: Include positions.h instead of options.h. + * src/search.h: Include positions.h instead of options.h. + * src/Makefile.in (OBJECTS): Add positions.o. + (POSITIONS_H): New variable. + (OPTIONS_H, SEARCH_H, OUTPUT_H, keyword.o): Use it. + (positions.o): New rule. + + * src/options.h (POSITIONS): New enum value. + (Positions::Positions): New copy constructor. + (Positions::operator=, Positions::contains, Position::add, + Positions::remove, Positions::print): New method declaration. + (Options::get_max_keysig_size): Remove method. + * src/options.icc (Positions::Positions): New copy constructor. + (Positions::operator=): New method. + (Options::get_max_keysig_size): Remove method. + * src/options.cc (Options::Options): Initialize _key_positions + trivially. + (Options::parse_options): Option -k sets POSITIONS. + (Positions::contains, Positions::add, Positions::remove, + Positions::print): New methods. + * src/hash-table.cc (Hash_Table::~Hash_Table): Compute the field + width explicitly, instead of using Options::get_max_keysig_size. + * src/keyword.h (KeywordExt::init_selchars): Add arguments + use_all_chars, positions. + (KeywordExt::delete_selchars): New declaration. + * src/keyword.cc (KeywordExt::init_selchars): Add arguments + use_all_chars, positions. Remove error message if there are no key + positions. + (KeywordExt::delete_selchars): New method. + * src/search.h: Include options.h. + (Search::preprepare, Search::init_selchars, Search::delete_selchars, + Search::count_duplicates, Search::find_positions): New declarations. + (Search::_key_positions): New field. + * src/search.cc (Search::Search): Initialize _key_positions. + (Search::preprepare, Search::init_selchars, Search::delete_selchars, + Search::count_duplicates, Search::find_positions): New functions. + (Search::prepare): Call preprepare and find_positions. Tweak error + message. + (Search::get_max_keysig_size): Use _key_positions instead of + option.get_key_positions(). + (Search::optimize): Tweak error message. + * src/output.h: Include options.h. + (Output::Output): Add Positions argument. + (Output::_key_positions): New field. + * src/output.cc (Output::Output): Add Positions argument. + (Output::output_hash_function): Omit the table if there are no + positions at all. Use _key_positions instead of + option.get_key_positions(). + (Output::output): Output the computed positions as a comment. + * src/main.cc (main): Pass the Positions from Searcher to Output. + * src/Makefile.in (SEARCH_H, OUTPUT_H): Include OPTIONS_H. + * tests/Makefile.in (check-test): Pass key positions explicitly. + * tests/gpc.exp: Update. + * tests/test-4.exp: Update. + * doc/gperf.texi (Algorithmic Details): Mention that -k is not needed + usually. + +2002-11-16 Bruno Haible + + * src/options.h (Options::get_slot_name): Renamed from + Options::get_key_name. + (Options::set, Options::set_language, Options::set_total_switches, + Options::set_function_name, Options::set_slot_name, + Options::set_class_name, Options::set_hash_name, + Options::set_wordlist_name, Options::set_delimiters): New method + declarations. + (Options::_language): New field. + (Options::_slot_name): Renamed from Options::_key_name. + * src/options.icc (Options::set): New method. + (Options::get_slot_name): Renamed from Options::get_key_name. + * src/options.cc (DEFAULT_FUNCTION_NAME): Renamed from DEFAULT_NAME. + (DEFAULT_SLOT_NAME): Renamed from DEFAULT_NAME. + (Options::Options): Initialize _language. Update. + (Options::~Options): Update. + (Options::set_language, Options::set_total_switches, + Options::set_function_name, Options::set_slot_name, + Options::set_class_name, Options::set_hash_name, + Options::set_wordlist_name, Options::set_delimiters): New methods. + (Options::parse_options): Call set_language. Update. + * src/input.cc (is_declaration, is_declaration_with_arg, + is_define_declaration): New functions. + (Input::read_input): Accept %DECL declarations. + * src/output.cc (Output::output_lookup_function_body): Update. + * doc/gperf.texi (Declarations): Add new subnodes. + (User-supplied Struct, Gperf Declarations, C Code Inclusion): New + nodes. + (Keywords, Output Format, Binary Strings, Options): Mention % + declarations as being equivalent to the command line options. + + * src/options.cc (Options::long_usage): Rename options -H, -N, -l, -G. + (long_options): Add --hash-function-name, --lookup-function-name, + --compare-lengths. + * doc/gperf.texi (Output Details): Rename options -H, -N, -l, -G. + * tests/test-6.exp: Update. + + * src/options.cc (DEFAULT_DELIMITERS): Remove newline. + * src/options.cc (Options::long_usage): Change default --delimiters. + * doc/gperf.texi (Input Details): Likewise. + * tests/test-6.exp: Update. + + * doc/gperf.texi: Move description of option -l from section + Algorithmic Details to section Output Details. + * src/options.cc (Options::long_usage): Likewise. + * tests/test-6.exp: Update. + +2002-11-12 Bruno Haible + + * src/options.h (Output::get_output_file_name): New method. + (Output::_output_file_name): New field. + * src/options.icc (Options::get_output_file_name): New method. + * src/options.cc (Options::long_usage): Document option --output-file. + (Options::Options): Initialize _output_file_name. + (long_options): Add --output-file. + (Options::parse_options): Handle it. + * src/main.cc (main): Open the output file if given by name. + * doc/gperf.texi (Output File): New section. + * tests/test-6.exp: Update. + +2002-11-10 Bruno Haible + + * src/input.cc (pretty_input_file_name): New function. + (read_input): Use it in all error and warning messages. + + * src/keyword.h (Keyword::_lineno): New field. + * src/input.h (Input::_struct_decl_lineno): New field. + * src/input.cc (Input::read_input): Set _struct_decl_lineno. Fill + each keyword's _lineno field. + * src/main.cc (main): Pass _struct_decl_lineno from Input to Output. + * src/output.h (Output::Output) Add struct_decl_lineno argument. + (Output::_struct_decl_lineno): New field. + * src/output.cc (Output::Output) Add struct_decl_lineno argument. + (output_keyword_entry): Emit #line directive before table entry. + (Output::output): Emit #line directive before _struct_decl. + + Fix memory leaks. + * src/keyword.h (empty_string): New declaration. + * src/keyword.cc (empty_string): New variable. + * src/input.h (Input::_input): Make public. + (Input::_input_end): New field. + * src/input.cc (read_input): When removing leading whitespace from + struct_decl, reallocate it. For rest, use empty_string instead of "". + Set _input_end. + (Input::~Input): Delete _struct_decl, _struct_tag, _return_type. + * src/search.cc (Search::prepare): When removing an element from + the keyword list, delete the list node. + (Search::~Search): Delete _occurrences, _asso_values. + * src/main.cc (main): Between Search::~Search and Input::~Input, + destroy the keyword list. + + Rewrite the input routines. + * src/input.h: Don't include read-line.h. + (Input): Don't inherit from class Read_Line. + (Input::read_keys, Input::strcspn, Input::set_output_types, + Input::get_array_type, Input::save_include_src, + Input::get_special_input): Remove declarations. + (Input::read_input): New declaration. + (Input::_struct_decl): Renamed from Input::_array_type. + (Input::_verbatim_declarations): Renamed from Input::_include_src. + (Input::_verbatim_code): Replaces Input::_additional_code. + * src/input.cc: Completely rewritten. + * src/output.h (Output::Output): Update the verbatim_* arguments. + (Output::_struct_decl): Renamed from Output::_array_type. + (Output::_verbatim_declarations): Renamed from Output::_include_src. + (Output::_verbatim_code): Replaces Output::_additional_code. + * src/output.cc (Output::Output): Update the verbatim_* arguments. + (Output::output): Output the verbatim_* code pieces with #line. + * src/main.cc (main): Call Input::read_input instead of + Input::read_keys. Update Output::Output arguments. + * src/read-line.h: Remove file. + * src/read-line.cc, src/read-line.icc: Remove files. + * src/Makefile.in (OBJECTS): Remove read-line.o. + (READ_LINE_H): Remove variable. + (INPUT_H): Update. + (read-line.o): Remove rule. + * doc/gperf.texi (Declarations): Correct the example. + (Keywords): Mention that lines starting with % are forbidden here. + * tests/c-parse.exp: Update. + * tests/cplusplus.exp: Update. + * tests/gpc.exp: Update. + * tests/java.exp: Update. + * tests/objc.exp: Update. + * tests/test-4.exp: Update. + + * src/options.h (Options::get_input_file_name): New declaration. + (Options::_input_file_name): New field. + * src/options.icc (Options::get_input_file_name): New method. + * src/options.cc (Options::Options): Initialize _input_file_name. + (Options::parse_options): Don't open input file, only store it in + _input_file_name. + * src/main.cc (main): Open input file here. + Print an error message upon write error on the output file. + + Upgrade to autoconf-2.52. + * configure.in: Use AC_CONFIG_SUBDIRS instead of AC_OUTPUT_SUBDIRS. + * Makefile.devel (configure, lib/configure, src/configure, + tests/configure, doc/configure): Use autoconf-2.52. + +2002-11-09 Bruno Haible + + * doc/gperf.texi: Talk about "bytes" instead of "characters". Talk + about "keywords", not "keys". Talk about "input file", not "keyfile". + (@menu): Fix a menu entry. + (Contributors): Don't mention cperf. + (Motivation): Fix an off-by-one error in the definition of "minimal". + Mention GNU Java. Recommend http URL instead of anonymous ftp. + (Search Structures): Mention GNU Java. + (Output Format): Drop reference to node 'Implementation'. + (Output Details): Talk about "slot-name" instead of "key name". + (Algorithmic Details): Talk about "selected byte positons", not + "key positions". Upper limit is now 255. Explain a third reason + why duplicates can occur. Describe negative effects of + --occurrence-sort. + (Implementation): Remove chapter. + +2002-11-07 Bruno Haible + + * src/bool-array.cc (Bool_Array::~Bool_Array): Free _storage_array. + * src/search.cc (Search::~Search): Free _union_set, _determined. + + * tests/Makefile.in (check-test): Don't redirect stderr. + +2002-11-05 Bruno Haible + + * src/keyword-list.h (mergesort_list): New declarations. + * src/keyword-list.cc (Keyword_Comparison): New type. + (merge, mergesort_list): New functions, moved here from search.cc. + * src/search.h (Search::merge, Search::merge_sort): Remove methods. + (Search::_occurrence_sort, Search::_hash_sort): Remove fields. + * src/search.cc (Search::merge, Search::merge_sort): Remove methods. + (greater_by_occurrence, less_by_hash_value): New functions. + (Search::reorder, Search::sort): Use mergesort_list. + +2002-11-04 Bruno Haible + + * src/options.h (Options::_asso_iterations): New field. + (Options::get_asso_iterations): New method declaration. + * src/options.icc (Options::get_asso_iterations): New method. + * src/options.cc (Options::short_usage): Mention j and m. + (Options::long_usage): Document option -m. + (Options::Options): Initialize _asso_iterations. + (Options::~Options): Print _asso_iterations too. + (long_options): Add --multiple-iterations. + (Options::parse_options): Handle option -m. + * src/keyword-list.h (copy_list, delete_list): New declarations. + * src/keyword-list.cc (copy_list, delete_list): New functions. + * src/search.h (Search::_initial_asso_value, Search::_jump): New fields. + * src/search.cc (Search::prepare_asso_values): Initialize + _initial_asso_value and _jump here. + (Search::init_asso_values): Use _initial_asso_value. + (Search::try_asso_value): Use _jump. + (Search::optimize): If option -m was given, iterate over different + values for _initial_asso_value and _jump. + * doc/gperf.texi (Algorithmic Details): Document option -m. + * tests/test-6.exp: Update. + +2002-11-03 Bruno Haible + + Bug fix: When option -j 0 was used without option -r, the output was + not random. + * src/search.h (Search::prepare_asso_values): New method declaration. + * src/search.cc (Search::prepare_asso_values): New method, extracted + from Search::init_asso_values. Call srand also when "-j 0" was given. + (Search::optimize): Call prepare_asso_values(). + + * src/hash-table.h (Hash_Table::_ignore_length, Hash_Table::equal): + Declare as const. + * src/hash-table.cc (Hash_Table::equal): Declare as const. + * src/input.h (Input::_factory): Declare as const. + * src/keyword-list.h (Keyword_List::first, KeywordExt_List::first): + Declare as const. + * src/keyword-list.icc (Keyword_List::first, KeywordExt_List::first): + Declare as const. + * src/output.h (Output::num_hash_values, Output::output_constants, + Output::output_hash_function, Output::output_keylength_table, + Output::output_keyword_table, Output::output_lookup_array, + Output::output_lookup_tables, Output::output_lookup_function_body, + Output::output_lookup_function, Output::_array_type, + Output::_additional_code, Output::_include_src, Output::_total_keys, + Output::_total_duplicates, Output::_max_key_len, Output::_min_key_len): + Declare as const. + * src/output.cc (Output::num_hash_values, Output::output_constants, + Output::output_hash_function, Output::output_keylength_table, + Output::output_keyword_table, Output::output_lookup_array, + Output::output_lookup_tables, Output::output_lookup_function_body, + Output::output_lookup_function): Declare as const. + * src/search.h (Search::merge, Search::merge_sort, + Search::compute_occurrence, Search::already_determined, + Search::keyword_list_length, Search::max_key_length, + Search::get_max_keysig_size, Search::compute_hash, + Search::sort_by_occurrence): Declare as const. + * src/search.cc (Search::merge, Search::merge_sort, + Search::compute_occurrence, Search::already_determined, + Search::keyword_list_length, Search::max_key_length, + Search::get_max_keysig_size, Search::compute_hash, + Search::sort_by_occurrence): Declare as const. + + * src/output.cc (Output::output): Set char_to_index to a cast in all + cases. Avoids gcc warnings on the generated code. + + * src/output.cc (Output_Enum): Prepend an underscore to field names. + (Output_Expr1): Likewise. + (Output::output_hash_function): Simplify the special case for "-k 1,$". + + * src/search.h (Search::init_asso_values, Search::find_asso_values): + New declarations. + (Search::try_asso_value): Renamed from Search::affects_prev. + (Search::change_some_asso_value): Renamed from Search::change. + (Search::set_asso_max, Search::get_asso_max): Remove methods. + (Search::_union_set): New field. + * src/search.cc (Search::init_asso_values): New method, extracted + from Search::optimize. + (Search::try_asso_value): Renamed from Search::affects_prev. Take the + iteration count as argument. + (Search::change_some_asso_value): Renamed from Search::change. Don't + make union_set static. Don't increment _fewest_collisions here. + (Search::find_asso_values): New method, extracted from + Search::optimize. + (Search::optimize); Update. + + * src/search.h (Search::compute_hash): Renamed from Search::hash. + (Search::compute_disjoint_union): Remove declaration. + (Search::sort_by_occurrence): Renamed from Search::sort_set. + * src/search.cc (Search::compute_hash): Renamed from Search::hash. + (compute_disjoint_union): Renamed from Search::compute_disjoint_union. + (Search::sort_by_occurrence): Renamed from Search::sort_set. + (Search::change): Simplify loop. + + * src/search.h (Search::clear_determined): New declaration. + * src/search.cc (Search::clear_determined): New method. + (Search::already_determined): Optimize. + (Search::reorder): Even when the next keyword after the current one + is completely determined, move all determined keywords after the + current one. + + Compute the occurrences after removal of duplicates, not before. + * src/keyword.h (KeywordExt::init_selchars): Remove occurrences + argument. + * src/keyword.cc (KeywordExt::init_selchars): Likewise. + * src/search.cc (Search::prepare): Reorder the code. Compute the + occurrences after removal of duplicates. + (Search::merge_sort): Optimize the loop. + (Search::compute_occurrence): Renamed from Search::get_occurrence. + * src/search.h (Search::compute_occurrence): Renamed from + Search::get_occurrence. + * tests/chill.exp: Regenerated. + + Bug fix: The hash table could fail to detect duplicates, between + keywords of different length, when option -n (option[NOLENGTH]) was + given. + * src/hash-table.h (Hash_Table::Hash_Table): Pass table size, not + vector and vector size as arguments. + (Hash_Table::_log_size): New field. + (Hash_Table::equal): New declaration. + * src/hash-table.cc (size_factor): New variable. + (Hash_Table::Hash_Table): Pass table size, not vector and vector size + as arguments. Allocate the vector here. + (Hash_Table::~Hash_Table): Deallocate the vector here. + (Hash_Table::equal): New function. + (Hash_Table::insert): Use it. Don't use item->_allchars_length for the + increment if _ignore_length is true. + * src/search.cc (TABLE_MULTIPLE): Remove variable. + (Search::prepare): Update. + +2002-11-02 Bruno Haible + + Provide documentation also in PDF format. + * doc/Makefile.in (pdfdir, TEXI2PDF): New variables. + (all): Depend on pdf. + (pdf, gperf.pdf): New rules. + (maintainer-clean): Remove the PDF file. + + * src/keyword-list.icc: New file, extracted from keyword-list.h. + * src/keyword-list.h: Include keyword-list.icc. Move inline methods + to there. + * src/keyword-list.cc: Include keyword-list.icc. + * src/Makefile.in (KEYWORD_LIST_H): Add keyword-list.icc. + + * lib/hashpjw.h (hashpjw): Change argument type to 'unsigned char *'. + * lib/hash.cc (hashpjw): Likewise. + * src/keyword.icc: New file. + * src/keyword.h: Include keyword.icc. + (KeywordExt::_selchars): Change type to 'unsigned char *'. + * src/keyword.cc: Include keyword.icc. + (Keyword::Keyword, KeywordExt::KeywordExt): Move to keyword.icc. + (sort_char_set): Change argument type to 'unsigned char *'. + (KeywordExt::init_selchars): Update. + * src/search.h (Search::compute_disjoint_union): Change argument types + to 'unsigned char *'. + (Search::sort_set): Likewise. + (Search::affects_prev): Change argument type to 'unsigned char'. + * src/search.cc (Search::prepare): Initialize _duplicate_link here. + (Search::get_occurrence, Search::set_determined, + Search::already_determined, Search::hash): Update. + (Search::compute_disjoint_union): Change argument types to + 'unsigned char *'. + (Search::sort_set): Likewise. + (Search::affects_prev): Change argument type to 'unsigned char'. + (Search::change): Update. + * src/Makefile.in (KEYWORD_H): Add keyword.icc. + + * src/options.cc (Options::parse_options): Fix error message. + + * src/read-line.h (Read_Line::Read_Line): Make FILE* argument + mandatory. Move body to read-line.icc. + * src/read-line.icc (Read_Line::Read_Line): New constructor. + * src/input.h (Input::Input): Add FILE* argument. + * src/input.cc (Input::Input): Likewise. + * src/main.cc (main): Pass stdin to Input constructor. + + * src/options.h (DEFAULTCHARS): Remove. + (Positions::MAX_KEY_POS): Set to 255. + (Positions::_positions): Increase array size. + (PositionIterator::EOS): Set to -1. + (PositionIterator::_index): Change type to 'unsigned int'. + * src/options.icc (Positions::Positions): Don't store + PositionIterator::EOS. + (PositionIterator::next): Produce PositionIterator::EOS here. + * src/options.cc (Options::long_usage): Use MAX_KEY_POS, not + MAX_KEY_POS-1. + (PositionStringParser): Rename field _size to _in_range. Rename + field _curr_value to _range_curr_value. Rename field _upper_bound + to _range_upper_bound. + (PositionStringParser::nextPosition): Comments. + (Options::Options): Update. + (Options::~Options): Update. + (long_options): Use NULL, not 0. + (Options::parse_options): Set BAD_VALUE to -2; -1 is now EOS. Bug fix: + Check against array overflow when more than MAX_KEY_POS positions are + given. Don't store PositionIterator::EOS. + Check against extra arguments before opening the input file. + * src/output.cc (Output::output_hash_function): Change test which + was for option[DEFAULTCHARS]. + * tests/test-6.exp: Update. + + * src/options.h (Options::get_delimiters): Renamed from + Options::get_delimiter. + * src/options.icc (Options::get_delimiters): Renamed from + Options::get_delimiter. + * src/input.cc (Input::read_keys): Update. + + Bug fix. + * src/options.cc (Options::print_options): Escape backquote inside + double-quoted strings. + + Bug fix. + * src/keyword.cc (KeywordExt::init_selchars): Avoid comparison with + uninitialized member variable. Found with 'valgrind'. + + * src/version.cc: Include version.h. + * src/Makefile.in (OBJECTS): Reorder. + (KEYWORD_H, KEYWORD_LIST_H, INPUT_H, SEARCH_H, OUTPUT_H): New + variables. + (HASH_TABLE_H): Update. + (options.o, read-line.o, keyword.o, keyword-list.o, input.o, search.o, + output.o, main.o): Update dependencies. + + * src/vectors.h: Remove file. + * src/vectors.cc: Remove file. + * src/search.h: Don't include vectors.h. + (Search): Don't inherit from Vectors. New fields _alpha_size, + _occurrences, _asso_values. + (Search::_determined, Search::get_occurrence, Search::set_determined, + Search::already_determined, Search::hash, Search::sort_set): Make + nonstatic. + * src/search.cc (Search::Search): Initialize _alpha_size, _occurrences, + _asso_values, _determined. + (Search::optimize, Search::~Search): Update. + * src/output.h: Don't include vectors.h. + (Output): Remove field _v. New fields _alpha_size, _occurrences, + _asso_values. + (Output::Output): Replace Vectors* argument with alpha_size, + occurrences, asso_values. + * src/output.cc (Output::Output): Replace Vectors* argument with + alpha_size, occurrences, asso_values. + (Output::output_hash_function): Update. + * src/main.cc (main): Don't set Vectors::ALPHA_SIZE. + Pass _alpha_size, _occurrences, _asso_values from Search to Output. + * src/keyword.h: Don't include vectors.h. + * src/Makefile.in (OBJECTS): Remove vectors.o. + (VECTORS_H): Remove variable. + (vectors.o): Remove rule. + + * src/search.h: New file, combines src/key-list.h, src/gen-perf.h. + * src/search,cc: New file, combines src/key-list.cc, src/gen-perf.cc. + * src/key-list.h: Remove file. + * src/key-list.cc: Remove file. + * src/gen-perf.h: Remove file. + * src/gen-perf.cc: Remove file. + * src/main.cc (KeywordExt_Factory): Moved here from gen-perf.cc. + (main): Inline some code from gen-perf.cc. + * src/keyword.h (KeywordExt::init_selchars): Take the occurrences + vector as argument. + * src/keyword.cc (KeywordExt::init_selchars): Take the occurrences + vector as argument. + * src/input.cc (Input::set_output_types): Initialize _array_type, + _return_type, _struct_tag. + (Input::read_keys): Initialize _additional_code. + * src/Makefile.in (OBJECTS): Add search.o. + Remove key-list.o, gen-perf.o. + (KEY_LIST_H, GEN_PERF_H): Remove variables. + (gen-perf.o, key-list.o): Remove rules. + (search.o): New rule. + + * *, */*: Update copyright notice to GPL version 2. + + * src/keyword-list.h (Keyword_List): New class. + (KeywordExt_List): Inherit from it. + * src/keyword-list.cc (Keyword_List::Keyword_List): New constructor. + (KeywordExt_List::KeywordExt_List): Update. + * src/input.h (Input::Input): Add Keyword_Factory argument. + (Input::_factory): New field. + (Input::_head): Change type to Keyword_List*. + (Input::parse_line): New declaration. + * src/input.cc (Input::Input): New constructor. + (Input::parse_line): Renamed from parse_line. Use the _factory. + (Input::read_keys): Update. + * src/key-list.cc (KeywordExt_Factory): New class. + (Key_List::read_keys): Pass a KeywordExt_Factory as Input constructor + argument. + + Avoid g++ -Wold-style-cast warnings. + * src/bool-array.icc: Use new-style casts. + * src/gen-perf.cc: Likewise. + * src/input.cc: Likewise. + * src/key-list.cc: Likewise. + * src/keyword.cc: Likewise. + * src/options.cc: Likewise. + * src/output.cc: Likewise. + * src/hash-table.cc: Likewise. Remove (char *) cast in memset argument. + + * src/keyword-list.h (KeywordExt_List): Don't inherit from KeywordExt. + (KeywordExt_List::KeywordExt_List): Take a KeywordExt* as argument. + (KeywordExt_List::_car): New field. + (KeywordExt_List::first): Use it. + * src/keyword-list.cc (KeywordExt_List::KeywordExt_List): Take a + KeywordExt* as argument. + * src/input.cc (parse_line): Create the KeywordExt separately. + + Start using bool. + * src/bool-array.h (Bool_Array::set_bit): Change return type to bool. + * src/bool-array.icc (Bool_Array::set_bit): Likewise. + * src/gen-perf.h (Gen_Perf::affects_prev): Likewise. + * src/gen-perf.cc (Gen_Perf::affects_prev): Likewise. + * src/hash-table.h (Hash_Table::_ignore_length): Change type to bool. + (Hash_Table::Hash_Table): Change 3rd argument type to bool. + * src/hash-table.cc (Hash_Table::Hash_Table): Likewise. + * src/input.h (Input::_additional_code): Change type to bool. + * src/input.cc (Input::read_keys): Update. + * src/key-list.h (Key_List::_occurrence_sort, Key_List::_hash_sort, + Key_List::_additional_code): Change type to bool. + (Key_List::_determined): Change element type to bool. + (Key_List::already_determined): Change return type to bool. + * src/key-list.cc (Key_List::_determined): Change element type to bool. + (Key_List::set_determined): Update. + (Key_List::already_determined): Change return type to bool. + (Key_List::reorder, Key_List::sort, Key_List::Key_List): Update. + * src/options.h (Positions::sort): Change return type to bool. + (Options::operator[]): Likewise. + * src/options.icc (Positions::sort): Change return type to bool. + (Options::operator[]): Likewise. + * src/output.h (Output::Output): Change 5th argument type to bool. + (Output::_additional_code): Change type to bool. + * src/output.cc (Output::Output): Change 5th argument type to bool. + +2002-10-16 Bruno Haible + + * src/*.h: Align all member names at column 24. + +2002-10-15 Bruno Haible + + * src/input.h: New file. + * src/input.cc: New file, extracted from key-list.cc. + * src/key-list.h (Key_List): Don't inherit from Read_Line. + (Key_List::get_special_input, + Key_List::save_include_src, Key_List::get_array_type, + Key_List::strcspn, Key_List::set_output_types): Remove methods. + * src/key-list.cc (Key_List::get_special_input, + Key_List::save_include_src, Key_List::get_array_type, + Key_List::strcspn, Key_List::set_output_types, parse_line): Move to + src/input.cc. + (Key_List::read_keys): Use Input::read_keys. + (Key_List::Key_List): Update. + * src/gen-perf.cc: Update. + * src/Makefile.in (OBJECTS): Add input.o. + (input.o): New rule. + +2002-10-14 Bruno Haible + + * src/options.cc: Don't include "vector.h". + (Options::parse_options): Don't initialize Vectors::ALPHA_SIZE here. + * src/vectors.cc (Vectors::ALPHA_SIZE): Don't initialize here. + * src/gen-perf.cc (Gen_Perf::Gen_Perf): Initialize Vectors::ALPHA_SIZE. + + * src/options.h (Positions): New class. + (PositionIterator): New class. + (Options::parse_options): Renamed from Options::operator(). + (Options::get_asso_max, Options::set_asso_max): Move to class Key_List. + (Options::reset, Options::get): Remove, replaced by class + PositionIterator. + (Options::get_initial_asso_value): Renamed from Options::initial_value. + (Options::key_sort): Remove, replaced by Positions::sort. + (Options): Make all fields and methods non-static. + * src/options.icc (Positions::Positions, Positions::operator[], + Positions::get_size, Positions::pointer, Positions::set_size, + Positions::sort, PositionIterator::PositionIterator, + PositionIterator::next): New methods. + (Options::get_initial_asso_value): Renamed from Options::initial_value. + (Options::get_size_multiple): New method. + (Options::get_key_positions): New method. + (Options::get_max_keysig_size): Implement using _key_positions. + * src/options.cc (Options::long_usage): Split big string into small + pieces. + (PositionStringParser): Prefix field names with _. + (Options::Options): Update. + (Options::~Options): Fix explanation of of _size_multiple. Don't print + _key_positions if it is effectively ignored. + (Options::parse_options): Renamed from Options::operator(). Update. + * src/key-list.h (Key_List): New field _size. New methods get_asso_max, + set_asso_max, get_max_keysig_size. + * src/key-list.cc (Key_List::read_keys): Don't make side effects on + options. + (Key_List::dump): Use Key_List::get_max_keysig_size() instead of + Options::get_max_keysig_size(). + (Key_List::get_max_keysig_size): New function. + * src/hash-table.cc (Hash_Table::~Hash_Table): Compute the field + width on the fly if option[ALLCHARS]. + * src/gen-perf.cc (Gen_Perf::Gen_Perf): Update, + Use Options::get_size_multiple() instead of Options::get_asso_max(). + Use Key_List::get_asso_max() instead of Options::get_asso_max(). Use + Key_List::get_max_keysig_size() instead of + Options::get_max_keysig_size(). + (Gen_Perf::affects_prev): Likewise. + (Gen_Perf::change): Likewise. + * src/keyword.cc: Update. + * src/main.cc: Update. + * src/output.cc: Update. + * tests/test-6.exp: Update. + +2002-10-13 Bruno Haible + + * src/bool-array.*: Some polishing. + + * src/options.h (Options::operator=, Options::operator!=): Remove + unused methods. + * src/options.icc (Options::operator=, Options::operator!=): Remove. + + * src/*.h: Prefix all field names with _. + * src/*.cc, src/*.icc: Update. + + * src/*: Simplify declarations of functions without arguments. + +2002-10-04 Bruno Haible + + * src/output.h: New file, extracted from key-list.h. + * src/output.cc: New file, extracted from key-list.cc. + * src/key-list.h (Key_List): Make some fields protected. Move output + routines to src/output.h. + * src/key-list.cc: Move output routines to src/output.cc. + * src/gen-perf.cc (Gen_Perf::doit_all): Use class Output. + * src/Makefile.in (OBJECTS): Add output.o. + (output.o): New rule. + +2002-10-03 Bruno Haible + + * src/iterator.h: Remove file. + * src/iterator.cc: Remove file. + * src/options.cc: (PositionStringParser): New class, taken from old + iterator.cc. + * src/Makefile.in (OBJECTS): Remove iterator.o. + (ITERATOR_H): Remove variable. + (iterator.o): Remove rule. + + * src/keyword-list.h: New file. + * src/keyword-list.cc: New file. + * src/list-node.h: Remove file. + * src/list-node.cc: Remove file. + * src/keyword.h (KeywordExt::init_selchars): New declaration. + * src/keyword.cc (sort_char_set, KeywordExt::init_selchars): New, from + old list-node.cc. + * src/gen-perf.cc: Replace List_Node by KeywordExt or KeywordExt_List, + as appropriate. + * src/hash-table.h: Likewise. + * src/key-list.h: Likewise. + * src/key-list.cc: Likewise. + * src/Makefile.in (OBJECTS): Remove list-node.o, add keyword-list.o. + (LIST_NODE_H): Remove macro. + (list-node.o): Remove rule. + (keyword-list.o): New rule. + + * src/keyword.h (KeywordExt): New class. + * src/keyword.cc (KeywordExt): New constructor. + * src/list-node.h (List_Node): Inherit from KeywordExt. + * src/list-node.cc: Update. + * src/gen-perf.cc: Update. + * src/hash-table.cc: Update. + * src/key-list.cc: Update. + (output_keyword_entry): Change argument type to KeywordExt*. + + * src/keyword.h: New file. + * src/keyword.cc: New file. + * src/list-node.h (List_Node): Extend Keyword. + * src/list-node.cc: Update. + * src/gen-perf.cc: Update. + * src/hash-table.cc: Update. + * src/key-list.cc: Update. + * src/Makefile.in (OBJECTS): Add keyword.o. + (keyword.o): New rule. + + * src/key-list.cc (Key_List::read_keys): Allocate the memory for the + hash table using 'new'. + (Key_List::output_lookup_array): Allocate the memory for the duplicates + array using 'new'. + * src/options.h (LARGE_STACK_ARRAYS): Remove definition. + * src/main.cc (main): Remove setrlimit call. + * src/configure.in: Don't test for unistd.h, sys/time.h, + sys/resource.h, getrlimit, setrlimit. + + * src/bool-array.h (Bool_Array): Make all members non-static. + Add an argument to the constructor. Remove init(), rename reset() to + clear(), rename find() to set_bit(). + * src/bool-array.icc: Move init() code into the constructor. + Rename reset() to clear(), rename find() to set_bit(). + * src/gen-perf.h (Gen_Perf): Add collision_detector member. + * src/gen-perf.cc: Update. + + * src/gen-perf.h (Gen_Perf::doit_all): Renamed from + Gen_Perf::operator (). + * src/gen-perf.cc (Gen_Perf::doit_all): Renamed from + Gen_Perf::operator (). + * src/main.cc: Update. + + * src/read-line.h (Read_Line::read_next_line): Renamed from + Read_Line::get_line. + * src/read-line.icc: Likewise. + * src/read-line.cc: Update. + * src/key-list.cc: Update. + + * lib/getline.h: New file. + * lib/getline.cc: New file. + * lib/Makefile.in (OBJECTS): Add getline.o. + (getline.o): New rule. + * src/read-line.h (Read_Line::readln_aux): Remove declaration. + * src/read-line.cc (Read_Line::readln_aux): Remove function. + * src/read-line.icc (Read_Line::get_line): Use ::get_line. + * src/options.h (LARGE_STACK): Remove macro. + + * src/bool-array.h (STORAGE_TYPE): Remove type. + Use 'unsigned int' instead of STORAGE_TYPE. + * src/bool-array.cc: Likewise. + * src/bool-array.icc: Likewise. + * src/gen-perf.cc: Likewise. + + * src/new.cc: Remove file. + * src/Makefile.in (OBJECTS): Remove new.o. + (new.o): Remove rule. + * src/configure.in: Remove test for HAVE_THROW_DECL. + * acconfig.h: Remove file. + + * src/trace.h: Remove file. + * src/trace.cc: Remove file. + * src/Makefile.in (OBJECTS): Remove trace.o. + (TRACE_H): Remove variable. + (trace.o): Remove rule. + Update all dependencies. + * src/bool-array.h, src/bool-array.cc, src/bool-array.icc: Don't use T. + * src/gen-perf.cc: Likewise. + * src/hash-table.cc: Likewise. + * src/iterator.cc: Likewise. + * src/key-list.cc: Likewise. + * src/list-node.cc: Likewise. + * src/main.cc: Likewise. + * src/new.cc: Likewise. + * src/options.h, src/options.cc, src/options.icc: Likewise. + * src/read-line.h, src/read-line.cc, src/read-line.icc: Likewise. + + * tests/Makefile.in: Use gperf option -I, to avoid gcc-3.x warnings. + * tests/test.c: Don't use gets(), to avoid warnings. + +2001-08-02 Bruno Haible + + * doc/gperf.texi: Change bug report address to . + * README: Updated. + +2000-12-18 Bruno Haible + + * src/configure.in: Add check for rand() in libm. Needed for BeOS. + * src/Makefile.in (LIBS): Use @GPERF_LIBM@ instead of hardwiring -lm. + +2000-11-20 Bruno Haible + + * doc/help2man: Update to version 1.23. + +2000-09-26 Bruno Haible + + * gperf-2.7.2 released. + + * doc/gperf.texi: Add a second bug report address + . + * README: Updated. + +2000-08-28 Bruno Haible + + * lib/getopt.h (struct option): Use "const" also when compiling in + C++ mode. Avoids warnings from Sun CC and HP-UX aCC. + + * doc/Makefile.in (docdir): Change from $(datadir)/doc/@PACKAGE@ to + $(prefix)/doc/@PACKAGE@, following the newest GNU standards. + +2000-08-20 Bruno Haible + + * src/version.cc: Bump version number to 2.7.2. + * doc/gperf.texi: Likewise. + + * doc/texinfo.tex: Update to post-texinfo-4.0 version. @code in the + title page now chooses a larger font. The overall layout of the + text is denser. + + * AUTHORS: New file. + + * tests/Makefile.in (all): Add check-lang-utf8 and check-lang-ucs2. + (check-lang-utf8, check-lang-ucs2): New targets. + (clean): Remove lu8out and lu2out. + * tests/lang-utf8.gperf, tests/lang-utf8.exp: New files. + * tests/lang-ucs2.gperf, tests/test2.c, tests/lang-ucs2.in, + tests/lang-ucs2.exp: New files. + + Allow the use of embedded NULs in keys. + * lib/hash.h (hashpjw): Add a length argument. + * lib/hash.cc (hashpjw): Likewise. Don't stop when encountering a NUL + character. + * src/hash-table.h (Hash_Table constructor): Add ignore_len argument. + (Hash_Table::ignore_length): New field. + (Hash_Table::insert): Renamed from Hash_Table::operator(). Remove + ignore_length argument. + * src/hash-table.cc (NIL): Remove macro. + (Hash_Table constructor): Add ignore_len argument. Use it to + initialize ignore_length. + (Hash_Table destructor): Specify explicit length of char_set and + key. + (Hash_Table::insert): Renamed from Hash_Table::operator(). Remove + ignore_length argument. Pass explicit length to hashpjw. Compare + char_set using memcmp, not strcmp. + * src/list-node.h (List_Node): Rename field length to key_length. + New field char_set_length. + (List_Node constructor): Accept key and rest, not the entire line. + * src/list-node.cc (List_Node constructor): Accept key and rest, not + the entire line. Don't NUL terminate key and char_set. Specify + explicit length of key. Initialize char_set_length field. + * src/key-list.cc: Include . + (parse_line): New function. + (Key_List::read_keys): Call parse_line instead of new List_Node. + Pass option[NOLENGTH] to Hash_Table constructor, not + Hash_Table::insert. Specify explicit length of key and char_set. + (Key_List::get_occurrence): Use explicit length of char_set. + (Key_List::set_determined): Likewise. + (Key_List::already_determined): Likewise. + (output_string): Add length argument. Output unprintable characters + using octal escape sequence. + (output_keyword_entry): Use explicit length of key. + (Key_List::output_lookup_array): Specify explicit length of key. + (output_switch_case): Likewise. + (Key_List::dump): Likewise. + * src/gen-perf.h (Gen_Perf::compute_disjoint_union): Add two length + arguments. + * src/gen-perf.cc (Gen_Perf::compute_disjoint_union): Likewise. Don't + stop when encountering NUL characters. Don't NUL terminate the + result. + (Gen_Perf::hash): Use explicit length of char_set. + (Gen_Perf::change): Specify explicit length of key. + * doc/gperf.texi: Document it. + + * doc/help2man: New file, help2man version 1.022. + * Makefile.devel (all): Add doc/gperf.1. + (doc/gperf.1): New target. + * doc/gperf.1: Automatically generated. + + * mkinstalldirs: New file, from automake-1.4, grep-2.4.1, guile-1.4, + libtool-1.3.3, make-3.79.1, tar-1.13. + * src/Makefile.in (MKINSTALLDIRS): New variable. + (install, installdirs): Use it instead of mkdir. + * doc/Makefile.in (MKINSTALLDIRS): New variable. + (install, installdirs): Use it instead of mkdir. + + * INSTALL: Update. + +2000-08-19 Bruno Haible + + * src/key-list.cc (Output_Compare_Memcmp): New class. + (Key_List::output_lookup_function): When option -l is given, use + memcmp instead of strcmp or strncmp. + + * doc/gperf.texi: The bug report address is . + The download address is ftp.gnu.org. Remove mention of -a and -g + options (now nops). Explain effect of -c option. + + * doc/configure.in (PACKAGE): New variable. + * doc/Makefile.in (datadir, docdir): New variables. + (dvidir, htmldir): Change values. + (install, installdirs): Update. + + * src/configure.in: Rename cache variable gp_cxx_throw_decl to + gp_cv_cxx_throw_decl. + + * src/key-list.cc (Key_List::output_hash_function): When outputting + __inline, take advantage of C++ compilers which have inline. + + * src/key-list.cc (Output_Compare_Strncmp::output_comparison): + After the call to strncmp, verify that expr2 is not longer than + `len'. + Reported by Carlo Wood . + + * src/key-list.cc (Key_List::output_lookup_function_body): Avoid + emitting the loop for dealing with duplicates if + total_duplicates == 0. + + * src/key-list.cc (Key_List::read_keys): Don't accept an empty key. + + * src/Makefile.in (install, installdirs, uninstall): Respect + $(DESTDIR). + * doc/Makefile.in (install, installdirs, uninstall): Likewise. + + * src/options.cc (Options::print_options): Escape the arguments which + contain special characters. + + * tests/c-parse.gperf: Updated from gcc-2.95.2/gcc/c-parse.gperf. + * tests/objc.gperf: New file, from gcc-2.95.2/gcc/objc/objc.gperf. + * tests/chill.gperf: New file, from gcc-2.95.2/gcc/ch/gperf. + * tests/cplusplus.gperf: New file, from gcc-2.95.2/gcc/cp/gxx.gperf. + * tests/gplus.gperf: Remove file. + * tests/java.gperf: New file, from gcc-2.95.2/gcc/java/keyword.gperf. + * tests/Makefile: Check them all. + * tests/c-parse.exp: Renamed from tests/test-1.exp. + * tests/modula2.exp: Renamed from tests/test-2.exp. + * tests/cplusplus.exp: Renamed from tests/test-3.exp. + * tests/gpc.exp: Renamed from tests/test-5.exp. + + * src/key-list.cc (output_switch_case): Add trailing semicolon to + lengthptr assignment line. Fixes bug with -D and -S. + From Reini Urban . Also reported by + David Hunter. + * tests/Makefile.in (check-lang-syntax): Perform each test with -D + once without and once with duplicates. + + * src/key-list.cc (output_keyword_entry): Avoid outputting a struct + initializer of the form {"key",}. + + * src/iterator.cc: Don't include . + From Michael Deutschmann . + + * tests/Makefile.in (VALIDATE, check-lang-syntax): Use $(srcdir) where + appropriate. + Reported by Andreas Schwab . + + * tests/validate: Don't run -traditional tests by default. + + * src/main.cc (main): Check for write error on stdout before returning. + + * src/Makefile.in (LDFLAGS): New definition, to catch the value given + at configure time. + + Make the structure initializers customizable. Based on a patch by + Kaveh R. Ghazi . + * src/options.h (Options::get_initializer_suffix, + Options::initializer_suffix): New declarations. + * src/options.icc (Options::get_initializer_suffix): New function. + * src/options.cc (DEFAULT_INITIALIZER_SUFFIX): New constant. + (Options::initializer_suffix): New variable. + (Options::short_usage): Document option "-F". + (Options::long_usage): Document option "-F". + (Options constructor): Initialize initializer_suffix. + (Options destructor): Dump initializer_suffix. + (long_options): Add option "-F". + (Options::operator()): Accept option "-F". Sets initializer_suffix. + * src/key-list.cc (output_keyword_blank_entries): Output + initializer_suffix. + * doc/gperf.texi: Document option "-F". + + * COPYING: Replace with GPL version 2 (with new FSF address and Y2K + safe year format). + + * doc/gpl.texinfo: New file. + * doc/gperf.texi: Document it. + * doc/Makefile.in (gperf.info, gperf.dvi, gperf.html, gperf_toc.html): + Update dependencies. + + * doc/Makefile.in (MAKEINFO): Unset LANG while running makeinfo. + +1998-05-20 Bruno Haible + + * doc/Makefile.in (gperf.dvi, clean): Remove gperf.cps. + (install, installdirs, uninstall): Don't install gperf.dvi. The + info and HTML documentations are sufficient for on-line use, and + users who wish to print the documentation (in PS or DVI format) + can do this directly off the source distribution. + (DVIPS): Use "-D600" instead of "-Pljfour", for portability. + +1998-05-20 Akim Demaille + + * doc/gperf.texi: Many modifications: + (Output Format): Declare `hash' and `in_word_set' as functions. + (Concept Index): New section. + (Title page): Use standard presentation. + (Top): Use @top instead of @unnumbered so that automatic master + update works. + (Motivation): Avoid spaces in @var. + (Options): Use the standard name ``Invoking ...''. + (Options): Declare also the long form of the options. + (Options): Remove redundant @itemize when @table is used. + +1998-05-08 Andreas Schwab + + * aclocal.m4 (CL_PROG_INSTALL): Set cl_cv_path_install, not + ac_cv_path_install. + +Sat May 2 13:20:54 1998 Bruno Haible + + * gperf-2.7 released. + +Sat May 2 12:31:51 1998 Bruno Haible + + * src/version.cc (version_string): Remove the "(C++ version)" suffix. + It's redundant: the early C versions of gperf are called cperf. + Reported by Karl Berry. + * src/option.cc (Options::operator()): Trim the output of "gperf -v". + +Thu Apr 16 13:22:16 1998 Bruno Haible + + * lib/Makefile.in, src/Makefile.in: Don't use $(TARGET_ARCH). + Solaris "make" sets it to a value not understood by "cc". + +Wed Apr 15 23:52:14 1998 Bruno Haible + + * lib/Makefile.in, src/Makefile.in: Don't use implicit rules. Don't + use $<. AIX "make" and OSF/1 "make" have problems with both. + * src/gen-perf.cc, src/key-list.cc: Cast free() argument to char*, + otherwise it doesn't compile on SunOS 4. + * src/key-list.h: Declare structs outside of other declarations, + needed for OSF/1 cxx 5.5. + * lib/getopt.h: Use prototypes if __STDC__ || __cplusplus. + Don't give a prototype for getopt(), to avoid error on SunOS 4. + * lib/getopt.c: Declare strncmp, to avoid warnings. + +Tue Apr 14 23:24:07 1998 Bruno Haible + + * lib/GetOpt.{h,cc}: Remove files. + * lib/getopt.{h,c}, lib/getopt1.c: New files, from GNU libc. + * lib/configure.in (AC_INIT): Search for hash.cc, not GetOpt.cc. + * lib/Makefile.in (OBJECTS): Remove GetOpt.o, add getopt.o, getopt1.o. + (getopt.o, getopt1.o, hash.o): Use explicit building rules. Some + "make"s don't support to have both implicit rules for "%.o : %.c" + and "%.o : %.cc" in the same Makefile. + * lib/hash.{h,cc}: Remove #pragma; there are no templates here. + * src/option.h (Options::usage): Remove. + (Options::short_usage, Options::long_usage): Declare. + * src/option.cc (Options::usage): Remove. + (Options::short_usage, Options::long_usage): New functions. + (long_options): New array. + (Options::operator()): Use getopt_long instead of GetOpt::operator(), + change all references to GetOpt members. + + * src/std-err.{h,cc}: Remove files. + * src/gen-perf.cc, src/key-list.cc, list-node.cc, new.cc, options.cc: + Call fprintf(stderr) instead of Std_Err::report_error(). + * src/key-list.h, src/list-node.h, src/options.h: Don't use class + Std_Err any more. + * src/option.cc (program_name): New variable. + * src/Makefile.in: Remove STD_ERR_H. + (OBJECTS): Remove std-err.o. + +Mon Mar 23 01:03:35 1998 Bruno Haible + + * aclocal.m4, {lib,src,tests}/configure.in: Remove CL_CC_WORKS and + CL_CXX_WORKS, already contained in autoconf 2.12. + + * src/gen-perf.cc, src/key-list.cc: Move some code from + Gen_Perf::Gen_Perf() to Key_List::output(). + * src/Makefile.in: Update dependencies. + + * src/options.{h,cc}: Remove option "-p". + * src/key-list.cc (Key_List::set_output_types): Rewrite. + (default_array_type, default_return_type): Remove. + * src/key-list.cc: Adjust "const" handling. + + With option "-t" [TYPE], don't emit wrong code if there is no + space before the struct's opening brace. + +Sun Mar 22 16:59:15 1998 Bruno Haible + + * src/key-list.{h,cc}: Completely reorganized the output routines. + Rewrote from scratch the output_switch() function. Use classes + (Output_Constants, Output_Expr, Output_Compare) for abstraction. + In particular: + + Don't emit trailing whitespace and spurious blank lines. + + Adjust indentation of the arrays. + + Don't emit commas at the end of array initializers and + struct initializers. + + With option "-l" [LENTABLE], compare the length before + fetching the word from memory. + + With option "-S" [SWITCH], emit the comparison code just once, + not once in every switch statement. + + With option "-S" [SWITCH], choose the right switch statement + through a binary search, not a linear search. + + With option "-S" [SWITCH], emit straightforward comparisons + instead of switch statements with just one "case" label. + + With options "-S -p -t" [SWITCH, POINTER, TYPE], don't emit + spurious empty elements at the beginning of the wordlist array. + + With option "-D" [DUP] and not option "-S" [SWITCH], if there + is no more room for duplicate entries in the lookup array, + don't call `assert (i != 0)'. Instead, make the array larger :-) + + With option "-D" [DUP], if there are no duplicates, don't + automatically fall back to the non-"-D" algorithm. If the user + wants the non-"-D" algorithm, he can just not specify "-D". + + With option "-D" [DUP] and either options "-p -t" [POINTER, TYPE] + or not option "-S" [SWITCH], don't emit spurious empty elements + at the beginning of the wordlist array. + + With option "-D" [DUP], simplify the detection and processing + of duplicate entries in the lookup array. + + With options "-D -l" [DUP, LENTABLE] and not option "-S" [SWITCH], + don't forget to emit the lengthtable array. + + With options "-D -l -S" [DUP, LENTABLE, SWITCH], don't forget to + compare the lengths before comparing the strings. + + * src/gen-perf.cc: No need to include . + * src/options.cc: Likewise. + + * src/options.cc: Don't use `errno' after freopen failed. + * src/std-err.cc: `report_error' doesn't call strerror(errno) any + more. No need to include and . + + * tests/Makefile.in (check-*): Any difference between .exp and .out + is a failure. Don't ignore whitespace differences. + + * tests/Makefile.in (check-lang-syntax): Add some more checks. + +Fri Mar 20 00:54:54 1998 Bruno Haible + + * tests/jscript.gperf: Renamed from tests/javascript.gperf, because + of Minix and SVR2 14-character filename limit. + * src/key-list.cc (output_string): New function. + (Key_List::output_switch, Key_List::output_keyword_table): Call it. + + * src/options.{h,icc,cc} (get_wordlist_name): New function. Add + option -W. + * src/key-list.cc (Key_List::output_switch, + Key_List::output_keyword_table, Key_List::output_lookup_function): + Use it. + Patch from William Bader . + + * src/version.cc: Bump version number directly from 2.5 to 2.7, + because Schmidt's last release from 1991 carries version number 2.6. + +Tue Jul 30 00:02:39 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * Fixed a small bug in the Key_List::output_keyword_table routine + that caused an extra newline to be printed if there where no + leading blank entries... (who cares, right?!) + +Mon Jul 29 22:05:40 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * Modified the handling of the -E (emit enums rather than + #defines) option in conjunction with the -G option. Now, if -G + and -E are given the enums are generated outside the lookup + function, rather than within it! + +Mon Apr 8 18:17:04 1991 Doug Schmidt (schmidt at net4.ics.uci.edu) + + * Yucko, there was a bug in the handling of -c (and of course the + new -I command in key-list.cc). Apparently when I added the + super-duper hack that provided support for duplicate keys I + forgot to update the strcmp output... + +Mon Mar 9 02:19:04 1998 Bruno Haible + + * Moved the documentation to doc/, put the stuff borrowed from + libg++ into lib/. + * Rewrote all Makefile.in's for better compliance with GNU standards. + * Autoconf based configuration. Rewrote all configure.in's. Added + aclocal.m4, with macros from CLISP and CLN. Added Makefile.devel. + * src/depend: Removed. Dependencies are now in src/Makefile.in. + + * src/bool-array.icc: New file, contains inline functions, from both + src/bool-array.h and src/bool-array.cc. + * src/options.icc: New file, contains inline functions, from both + src/options.h and src/options.cc. + * src/read-line.icc: New file, contains inline functions, from both + src/read-line.h and src/read-line.cc. + + * src/bool-array.h: Don't include . + * src/bool-array.cc: Include . + * src/gen-perf.cc: No need to include . Don't include + <_G_config.h>. + * src/hash-table.cc: Don't include and . Include + and lib/hash.h instead. + * src/iterator.cc: Don't include . + * src/key-list.cc: Don't include . Include and + instead. + * src/list-node.cc: Don't include . Include instead. + Remove `index' hack. + * src/main.cc: Don't include <_G_config.h>. + * src/new.cc: Don't include . Include instead. + * src/options.cc: Don't include . Include and + instead. + * src/read-line.cc: Don't include . Include + instead. + * src/std-err.cc: Don't include . Include (for Irix). + * src/vectors.h: No need to include . + * src/version.cc: No need to include . + + * src/bool-array.h: Change `STORAGE_TYPE' from int to unsigned int. + * src/bool-array.{h,cc}: Change type of `Bool_Array::size' from int + to unsigned int. + * src/bool-array.{h,cc}: Change type of `Bool_Array::init' argument + from STORAGE_TYPE to unsigned int. + * src/gen-perf.{h,cc}: Change two `Gen_Perf::compute_disjoint_union' + argument types from `char *' to `const char *'. + * src/iterator.h: Change type of `Iterator::str' and argument of + `Iterator::Iterator' from `char *' to `const char *'. + * src/iterator.cc: Cast to `unsigned char' before calling `isdigit'. + * src/key-list.{h,cc}: Change type of `Key_List::array_type', + `Key_List::return_type', `Key_List::struct_tag', + `Key_List::include_src', `default_array_type', `default_return_type' + and return type of `Key_List::get_array_type', + `Key_List::get_special_input', `Key_List::save_include_src' from + `char *' to `const char *'. + * src/key-list.cc: Change "pretty gross" assignment. + * src/key-list.cc: Don't use `alloca', HP-UX CC lacks it. + * lib/GetOpt.cc: Likewise. + * src/key-list.cc (merge): Use iteration instead of recursion. + * src/list-node.{h,cc}: Change type of `List_Node::key', + `List_Node::rest', `List_Node::char_set' from `char *' to + `const char *'. + * src/new.cc: Don't use BUFSIZ. Conditionalize the throw() declaration. + * src/read-line.h: Don't use BUFSIZ. + * src/read-line.cc: Make CHUNK_SIZE a constant, and use allocate the + buffers on the stack by default. Use memcpy for copying buffers. + Include . + * src/read-line.icc (get_line): Use iteration instead of tail recursion. + Don't call ungetc(EOF,stdin). + * src/std-err.{h,cc}: Change type of `Std_Err::program_name' and of + argument `Std_Err::report_error' from `char *' to `const char *'. + * src/std-err.cc: `report_error' doesn't call `exit' any more. All + callers changed to do that themselves. + * src/trace.h: Make constructor/destructor calls non-inline. + + * src/key-list.cc (output_hash_function): If option[CPLUSPLUS], + always make the hash function inline. + (output): Declare the hash function inline, with the right name. + * src/options.{h,cc}, src/gen-perf.cc, src/key-list.cc: Remove + options -g, making it on by default. Remove option -a. Instead, + introduce "-L KR-C", "-L C", "-L ANSI-C", "-L C++". + * src/options.{h,cc}, src/key-list.cc: Add option -I. + * src/key-list.cc: Don't emit "const" if compiling in mode "-L KR-C". + * src/key-list.cc: Don't emit a comma at the end of an enum list. + * src/main.cc: Remove COUNT_TIME code. + * src/vectors.h, src/key-list.cc, src/options.cc, src/list-node.cc: + ALPHA_SIZE defaults to 256 now. Add option -7. + + * tests/javascript.gperf: New file. + * tests/jstest*.gperf, tests/validate: New tests. + +Sat Jan 31 01:38:11 1998 Alexandre Oliva + + * src/Makefile.in ($(TARGETPROG)): Add $(CFLAGS). + +Wed Jan 28 01:56:00 1998 Manfred Hollstein + + * configure.in (package_makefile_rules_frag): New and + redirect stderr from ${srcdir}/config.shared to + ${package_makefile_rules_frag}. + * src/configure.in: Ditto. + * tests/configure.in: Ditto. + +Fri Jan 23 08:00:41 1998 H.J. Lu (hjl@gnu.org) + + * gperf.texi (@ichapter): Changed to @chapter. + +Wed Jan 14 09:16:48 1998 H.J. Lu (hjl@gnu.org) + + * src/key-list.cc, src/key-list.h (Key_List::strcspn): Don't + define if strcspn is defined. + +Fri Jan 24 13:23:47 1997 Mike Stump + + * src/new.cc (operator delete): Add the exception specification. + +Mon Feb 5 19:29:16 1996 Per Bothner + + * src/read-line.cc (Read_Line::readln_aux): Handle EOF if last line + has a length which is an exact multiple of CHUNK_SIZE. (Used to throw + away the line's contents.) From Bruno Haible . + * src/Makefile.in ($(TARGETPROG)): Add -lm to link line. + +Tue Jun 11 13:43:50 1996 Brendan Kehoe + + * src/list-node.cc (List_Node): Reorder init of nodes to + match declaration order. + * src/hash-table.cc (Hash_Table): Likewise. + +Tue Oct 10 16:37:28 1995 Mike Stump + + * src/new.cc: Since malloc/delete are not paired, we cannot call + free. + +Wed Jan 4 12:40:14 1995 Per Bothner + + * src/Makefile.in ($(TARGETPROG)): Link with $(LDFLAGS). + Patch from John Interrante . + +Sat Nov 5 19:12:48 1994 Jason Merrill (jason@phydeaux.cygnus.com) + + * src/Makefile.in (LIBS): Remove. + +Tue Oct 18 17:51:14 1994 Per Bothner + + * src/std-err.cc: Use stderror, instead of the non-standard + sys_nerr and sys_errlist. + +Sat Sep 17 22:02:13 1994 Per Bothner (bothner@kalessin.cygnus.com) + + * src/key-list.cc (output_hash_function): + Patch from William Bader . + +Fri Jul 15 09:38:11 1994 Per Bothner (bothner@cygnus.com) + + * src/std-err.cc: #include , and only declare + extern int errno if errno is not a macro. + +Mon May 30 17:29:34 1994 Per Bothner (bothner@kalessin.cygnus.com) + + * Makefile.in (src_all, install): Make sure to add '/' after + `pwd` in $rootme, as expected by FLAGS_TO_PASS. + +Wed May 11 00:47:22 1994 Jason Merrill (jason@deneb.cygnus.com) + + Make libg++ build with gcc -ansi -pedantic-errors + * src/options.h: Lose commas at end of enumerator lists. + +Sun Dec 5 19:16:40 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + + * src/hash-table.cc (Hash_Table::~Hash_Table): Don't pass an + argument to fprintf, since it's not expecting one. + +Fri Nov 26 19:03:18 1993 Per Bothner (bothner@kalessin.cygnus.com) + + * src/list-node.cc: #undef index, for the sake of broken NeXT, + +Thu Nov 4 11:16:03 1993 Per Bothner (bothner@kalessin.cygnus.com) + + * Makefile.in (install): Use INSTALL_DATA for gperf.1. + +Mon Oct 25 18:40:51 1993 Per Bothner (bothner@kalessin.cygnus.com) + + * src/key-list.cc (Key_List::read_keys): Use POW macro + to increase hash table size to power of 2. + + * options.h (LARGE_STACK_ARRAYS): New flag. Defaults to zero. + * gen-perf.cc, key-list.cc, read-line.cc: + Only stack-allocate large arrays if LARGE_STACK_ARRAYS is set. + * main.cc (main): Only call setrlimit (RLIMIT_STACK, ...) + if LARGE_STACK_ARRAYS. + +Mon Oct 4 17:45:08 1993 Per Bothner (bothner@kalessin.cygnus.com) + + * src/gen-perf.cc: Always use ANSI rand/srand instead of BSDisms. + +Wed Aug 18 12:19:53 1993 Per Bothner (bothner@kalessin.cygnus.com) + + * Makefile.in (src_all): Make less verbose output. + +Fri May 28 14:01:18 1993 Per Bothner (bothner@rtl.cygnus.com) + + * src/gen-perf.cc (Gen_Perf::change): Don't use gcc-specific + 2-operand conditional expression. + * src/key-list.cc (Key_List::output_lookup_array): + Don't use variable-size stack arrays, unless compiled by g++. + +Tue May 4 14:08:44 1993 Per Bothner (bothner@cygnus.com) + + Changes (mostly from Peter Schauer) to permit compilation + using cfront 3.0 and otherwise be ARM-conforming. + * src/key-list.h: class Key_List must use public derivation + of base class Std_Err (because Gen_Perf::operator() in gen-perf.cc + calls Std_Err::report_error). + * src/gen-perf.cc (Gen_Perf::affects_prev), src/hash-table.cc + (Hash_Table::operator()): Don't use gcc-specific 2-operand + conditional expression. + * src/iterator.cc (Iterator::operator()): Don't use gcc-specific + range construct in case label. + * key-list.cc (Key_List::output_lookup_array, Key_List::read_keys), + src/gen-perf.cc (Gen_Perf::operator(), src/read-line.cc + (Read_Line::readln_aux): If not gcc, don't allocate + variable-sized arrays on stack. + * src/new.cc (operator new): Argument type should be size_t. + * key-list.cc (Key_List::output_lookup_array, Key_List::read_keys), + new/cc (::operator new): Don't use non-standard >?= operator. + +Tue Apr 27 20:11:30 1993 Per Bothner (bothner@cygnus.com) + + * src/Makefile.in: Define TARGETPROG, and use it. + +Mon Apr 19 00:29:18 1993 Per Bothner (bothner@cygnus.com) + + * Makefile.in, configure.in: Re-vamped configure scheme. + * gperf.texinfo: Renamed to gperf.texi. + * src/bool-array.{h,cc}: ANSIfy bzero->memset. + +Sat Jan 30 20:21:28 1993 Brendan Kehoe (brendan@lisa.cygnus.com) + + * tests/Makefile.in (mostlyclean): Also delete aout, cout, m3out, + pout, and preout. + +Tue Dec 29 08:58:17 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: pass $(FLAGS_TO_PASS) to all calls to make. + (FLAGS_TO_PASS): added INSTALL, INSTALL_DATA, INSTALL_PROGRAM. + +Mon Dec 21 18:46:46 1992 Per Bothner (bothner@rtl.cygnus.com) + + * tests/expected.* renamed to *.exp to fit in 14 chars. + * tests/Makefile.in: Update accordingly. + Also rename output.* to *.out. + * src/Makefile.in (clean): Remove gperf program. + +Wed Dec 9 14:33:34 1992 Per Bothner (bothner@cygnus.com) + + * src/hash-table.cc, src/bool-array.h: ANSIfy bzero->memset. + +Thu Dec 3 19:34:12 1992 Per Bothner (bothner@cygnus.com) + + * Makefile.in (distclean, realclean): Don't delete + Makefile before recursing. + +Fri Nov 6 13:41:49 1992 Per Bothner (bothner@rtl.cygnus.com) + + * key-list.{h,cc}: Remove MAX_INT (and similar) constant + fields from Key_List class, and use INT_MAX (etc) from limits.h. + * key-list.{h,cc}, options.{h,cc}, vectors.h: Removed all + uses of initialized const fields, as they are non-standard + - and their use was easy to do away with. Mostly, just + made the constants static non-fields in the .cc file. + +Mon Nov 2 13:10:11 1992 Per Bothner (bothner@cygnus.com) + + * tests/Makefile.in: When generating cinset.c, don't pass -C, + since -C assumes an ANSI compiler. Add the -C flag (with -a) + when generating test.out.3 instead. + * tests/expected.out.3: Update accordingly. + +Wed Aug 12 11:47:54 1992 Per Bothner (bothner@cygnus.com) + + * Makefile.in: Factor out common flags into $(FLAGS_TO_PASS). + * Makefile.in: 'install-info' depends on gperf.info. + +Mon Aug 10 11:39:52 1992 Ian Lance Taylor (ian@dumbest.cygnus.com) + + * Makefile.in, src/Makefile.in: always create installation + directories. + +Mon Jul 20 15:33:21 1992 Mike Stump (mrs@cygnus.com) + + * src/new.cc (operator new): Add cast from void * to char *, + since it is not a standard conversion. + +Wed Jun 17 16:25:30 1992 Per Bothner (bothner@rtl.cygnus.com) + + * src/gen-perf.cc: #include <_G_config.h> for _G_SYSV. + * src/key-list.cc: alloca() hair. + * src/main.cc (main): Only call getrlimit if _G_HAVE_SYS_RESOURCE. + * Makefile,in, {src,test}/Makefile.in: Fix *clean rules. + +Fri May 29 13:21:13 1992 Per Bothner (bothner@rtl.cygnus.com) + + * src/gen-perf.cc: Replace USG -> _G_SYSV. + +Thu May 14 13:58:36 1992 Per Bothner (bothner@rtl.cygnus.com) + + * src/Makefile.in: Don't pass obsolete flag -DUNLIMIT_STACK. + * tests/Makefile.in (clean): Fix. + +Sat Mar 7 00:03:56 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * gperf.texinfo: added menu item hook. + +Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in, configure.in: removed traces of namesubdir, + -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced + copyrights to '92, changed some from Cygnus to FSF. + +Sun Jan 26 19:21:58 1992 Per Bothner (bothner at cygnus.com) + + * tests/Makefile.in: Use re-directed stdin instead of file + name in argv. This allows us to remove the filename + from the output, the expected output, and hence the diffs. + (Note that the input file is in $(srcdir), which we cannot + place in the expected out files.) + * tests/expected.out.[1235]: Edit out input filename, + to match new output. + +Thu Jun 28 16:17:27 1990 Doug Schmidt (schmidt at brilliant) + + * Wow, first fix on the new job! There was a dumb error + in Key_List::output_lookup_function, where I printed the + string "&wordlist[key]" instead of the correct "&wordlist[index]". + + * Added a couple of #ifdefs for USG support. + +Sun Jun 3 17:16:36 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Updated the version number to 2.5 and sent to Doug Lea for release + with the latest GNU libg++. + + * Changed the error handling when a keyword file cannot be opened + (now calls perror). + +Wed May 30 14:49:40 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Instrumented the source code with trace statements automagically + inserted using my new automated trace instrumentation tool! + +Wed May 9 11:47:41 1990 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Really fixed the previous bug. Turns out that a small amount + of logic had to be duplicated to handle static links that occur + as part of dynamic link chains. What a pain!!! + +Tue May 8 23:11:44 1990 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Fixed a stupid bug in Key_List::output_lookup_array that was + causing incorrect counts to be generated when there were both + static and dynamic links occurring for the same hash value. + Also simplified the code that performs the logic in this routine. + +Mon Apr 30 17:37:24 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Fixed stupid bug in Key_List::output_lookup_array that was + making the generated lookup[] array contain `chars' even + when the values stored in the chars are greater than 127! + + * Changed the behavior of the -G (global table) option so that it + will output the `length[]' array in the global scope along with + the `word_list[]' array. + + * Fixed a stupid bug in Key_List::output_lookup_function that + would always output the complicated `duplicate-handling' lookup + logic, even when there were no duplicates in the input! + + * Yikes, had to modify a bunch of stuff in key-list.cc to correctly + handle duplicate entries. Changed the generated code so that + the MIN_HASH_VALUE is no longer subtracted off when calculating + the hash value for a keyword. This required changing some other + code by substituting MAX_HASH_VALUE for TOTAL_KEYS in several places. + Finally, this means that the generated tables may contain leading + null entries, but I suppose it is better to trade-off space to get + faster performance... + +Mon Mar 26 13:08:43 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Updated version number to 2.4 to reflect the latest changes. + + * Changed the main program so that it always prints out gperf's + execution timings to the generated output file. + +Sun Mar 25 12:39:30 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Added the -Z option so that users can specify the name of the + generated class explicitly. Updated documentation to reflect + this change. + + * Modified the generated C++ class interface so that the functions + are declared static (to remove the overhead of passing the `this' + pointer). This means that operator()() can no longer be used, + since it only works on non-static member functions. + Also changed things so that there is no constructor (why waste + the extra call, when it doesn't do anything, eh?) + + * Modified the behavior of Key_List::output when the -L C++ option + is enabled. Previously the code generated use const data members + to record MIN_WORD_LENGTH, MIN_HASH_VALUE, etc. However, as + pointed out by James Clark this may result in suboptimal behavior + on the part of C++ compilers that can't inline these values. + Therefore, the new behavior is identical to what happens with + -L C, i.e., either #defines or function-specific enums are used. + Why sacrifice speed for some abstract notion of `code purity?' ;-) + +Tue Mar 6 18:17:42 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Added the -E option that defines constant values using an enum + local to the lookup function rather than with #defines. This + also means that different lookup functions can reside in the + same file. Thanks to James Clark (jjc@ai.mit.edu). + +Sat Mar 3 20:19:00 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Added a special case to key_list::output_switch that doesn't + generate extra comparisons when the `-S' is given an argument + of 1 (the normal case). This should speed up the generated + code output a tad... + +Fri Feb 23 14:21:28 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Renamed all instances of member function get_keysig_size + to get_max_keysig_size, since this is more precise... + + * Changed all occurrences of charset to keysig (stands for ``key + signature'') to reflect the new naming convention used in the + USENIX paper. + +Thu Feb 22 11:28:36 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Changed the name of the generated associated values table from + asso_value to asso_values to reflect conventions in the USENIX + C++ paper. + +Thu Feb 15 23:29:03 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Updated the gperf.texinfo file to fix some formatting problems + that had crept in since last time. + +Wed Feb 14 23:27:24 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Fixed stupid bug in key-list.cc (get_special_input), wher + gperf replaced each '%' with the succeeding character. + + * Added support for multiple target language generation. Currently + handled languages are C and C++, with C as the default. Updated + documentation and option handler to reflect the changes. + + * Added a global destructor to new.cc and removed the #ifdef, since + the bloody thing now works with libg++. + +Mon Feb 14 13:00:00 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Found out that my gperf paper was accepted at the upcoming + USENIX C++ Conference in San Francisco. Yow! + +Tue Jan 30 09:00:29 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * #ifdef'd out the new.cc memory allocator, since there are + problems with this and the libg++ stuff. + + * Changed key-list.h so that class Vectors is a public (rather + than private) base class for class Key_List. The previous + form was illegal C++, but wasn't being caught by the old + g++ compiler. Should work now... ;-) + +Sun Dec 10 14:08:23 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added several changes from rfg@ics.uci.edu. These changes + help to automate the build process. + +Wed Nov 15 15:49:33 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Removed conditional compilation for GATHER_STATISTICS. There's + really no good reason to avoid collecting this info at run-time, + since that section of code is *hardly* the bottleneck... ;-) + + * Simplified the C output routines in Key_List::set_output_types + and Key_List::output_keyword_table a bit in order to + speed-up and clean up the code generation. + + * Modified function Key_List::get_special_input so that it does + not try to `delete' a buffer that turned out to be too short. + This is important since the new memory management scheme + does not handle deletions. However, adding a small amount of + garbage won't hurt anything, since we generally don't do this + operation more than a couple times *at most*! + + * Created a new file (new.cc) which includes my own overloaded + operator new. This function should dramatically reduce the + number of calls to malloc since it grabs large chunks and + doles them out in small pieces. As a result of this change + the class-specific `operator new' was removed from class List_Node. + +Tue Nov 14 21:45:30 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Continued to refine the great hack. The latest trick is to + try and replace most uses of dynamic memory (i.e., calls to + new) with uses of gcc dynamic arrays (i.e., an alloca solution). + This makes life much easier for the overall process-size, since + it reduces the amount of overhead for memory management. As a + side-effect from this change there is no reason to have the + Bool_Array::dispose member function, so it's outta here! + + * Fixed a stupid bug that was an disaster waiting to happen... + Instead of making the boolean array large enough to index + max_hash_value it was only large enough to index max_hash_value + - 1. Once again, an off-by-one mistake in C/C++!!!! + +Mon Nov 13 19:38:27 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added the final great hack! This allows us to generate hash tables + for near-perfect hash functions that contain duplicates, *without* + having to use switch statements! Since many compilers die on large + switch statements this feature is essential. Furthermore, it appears + that the generated code is often *smaller* than that put out by + compilers, even though a large, sparse array must be created. + Here's the general idea: + + a. Generate the wordlist as a contiguous block of keywords, + just as before when using a switch statement. This + wordlist *must* be sorted by hash value. + + b. Generate the lookup array, which is an array of signed + {chars,shorts,ints}, (which ever allows full coverage of + the wordlist dimensions). If the value v, where v = + lookup[hash(str,len)], is >= 0 and < TOTAL_KEYWORDS, then we + simply use this result as a direct access into the wordlist + array to snag the keyword for comparison. + + c. Otherwise, if v is < -TOTAL_KEYWORDS or > TOTAL_KEYWORDS + this is an indication that we'll need to search through + some number of duplicates hash values. Using a hash + linking scheme we'd then index into a different part of + the hash table that provides the starting index and total + length of the duplicate entries to find via linear search! + +Sun Nov 12 13:48:10 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Simplified Key_List::output_min_max considerably by recognizing + that since the keyword list was already sorted by hash value finding + the min and max values is trivial! + + * Improved the debugging diagnostics considerably in classes Key_List, + Hash_Table, and Gen_Perf. + + * Modified the `-s' option so that a negative argument is now + interpreted to mean `allow the maximum associated value to be + about x times *smaller* than the number of input keys.' This + should help prevent massive explosion of generated hash table + size for large keysets. + +Sat Nov 11 11:31:13 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added a field in class Key_List that counts the total number + of duplicate keywords, both static and dynamic. + + * Added a new member function Bool_Array that deletes the dynamic + memory allocated to Bool_Array::storage_array. This space may + be needed for subsequent options, so it made sense to free it as + soon as possible... + + * Renamed file/class Alpha_Vectors to Vectors, to avoid problems + with 14 character length filenames on SYSV. Also changed file + adapredefined.gperf to adadefs.gperf in the ./tests directory. + + * Modified class Options by changing the member function + Options::total_positions to Options::get_charset_size and + Options::set_charset_size. These two routines now either return + the total charset size *or* the length of the largest keyword + if the user specifies the -k'*' (ALLCHARS) option. This change + cleans up client code. + + * Merged all the cperf changes into gperf. + + * Made sure to explicitly initialize perfect.fewest_collisions to + 0. + + * Cleaned up some loose ends noticed by Nels Olson. + 1. Removed `if (collisions <= perfect.fewest_collisions)' + from Gen_Perf::affects_prev since it was superfluous. + 2. Removed the fields best_char_value and best_asso_value + from Gen_Perf. There were also unnecessary. + 3. Fixed a braino in the Bool_Array::bool_array_reset + function. Since iteration numbers can never be zero + the `if (bool_array.iteration_number++ == 0)' must be + `if (++bool_array.iteration_number == 0).' + 4. Modified Std_Err::report_error so that it correctly handles + "%%". + + * It is important to note that -D no longer enables -S. + There is a good reason for this change, which will become + manifested in the next release... (suspense!). + + * Made some subtle changes to Key_List::print_switch so that if finally + seems to work correctly. Needs more stress testing, however... + + * Made a major change to the Key_List::print_switch function. + The user can now specify the number of switch statements to generate + via an argument to the -S option, i.e., -S1 means `generate 1 + switch statement with all keywords in it,' -S2 means generate + 2 switch statements with 1/2 the elements in each one, etc. + Hopefully this will fix the problem with C compilers not being + able to generate code for giant switch statements (but don't + hold your breath!) + + * Changed Key_List::length function to Key_List::keyword_list_length. + + * Added a feature to main.c that prints out the starting wall-clock + time before the program begins and prints out the ending wall-clock + time when the program is finished. + + * Added the GATHER_STATISTICS code in hash-table.c so we can + keep track of how well double hashing is doing. Eventually, + GATHER_STATISTICS will be added so that all instrumentation + code can be conditionally compiled in. + + * Fixed a stupid bug in Key_List::print_switch routine. This + was necessary to make sure the generated switch statement worked + correctly when *both* `natural,' i.e., static links and dynamic + links, i.e., unresolved duplicates, hash to the same value. + + * Modified Bool_Array::~Bool_Array destructor so that + it now frees the bool_array.storage_array when it is no longer + needed. Since this array is generally very large it makes sense + to return the memory to the freelist when it is no longer in use. + + * Changed the interface to constructor Hash_Table::Hash_Table. This + constructor now passed a pointer to a power-of-two sized buffer that + serve as storage for the hash table. Although this weakens information + hiding a little bit it greatly reduces dynamic memory fragmentation, + since we can now obtain the memory via a call to alloca, rather + than malloc. This change modified Key_List::read_keys calling + interface. + + * Since alloca is now being used more aggressively a conditional + compilation section was added in main.c. Taken from GNU GCC, + this code gets rid of any avoidable limit on stack size so that + alloca does not fail. It is only used if the -DRLIMIT_STACK + symbol is defined when gperf is compiled. + + * Added warnings in option.c so that user's would be informed + that -r superceeds -i on the command-line. + + * Rewrote Gen_Perf::affects_prev. First, the code structure + was cleaned up considerably (removing the need for a dreaded + goto!). Secondly, a major change occurred so that Gen_Perf::affects_prev + returns FALSE (success) when fewest_hits gets down to whatever + it was after inserting the previous key (instead of waiting for + it to reach 0). In other words, it stops trying if it can + resolve the new collisions added by a key, even if there are + still other old, unresolved collisions. This modification was + suggested by Nels Olson and seems to *greatly* increase the + speed of gperf for large keyfiles. Thanks Nels! + + * In a similar vein, inside the Gen_Perf::change routine + the variable `perfect.fewest_collisions is no longer initialized + with the length of the keyword list. Instead it starts out at + 0 and is incremented by 1 every time change () is called. + The rationale for this behavior is that there are times when a + collision causes the number of duplicates (collisions) to + increase by a large amount when it would presumably just have + gone up by 1 if none of the asso_values were changed. That is, + at the beginning of change(), you could initialize fewest_hits + to 1+(previous value of fewest_hits) instead of to the number of + keys. Thanks again, Nels. + + * Replaced alloca with new in the Gen_Perf::change function. + This should eliminate some overhead at the expense of a little + extra memory that is never reclaimed. + + * Renamed Gen_Perf::merge_sets to Gen_Perf::compute_disjoint_union + to reflect the change in behavior. + + * Added the -e option so users can supply a string containing + the characters used to separate keywords from their attributes. + The default behavior is ",\n". + + * Removed the char *uniq_set field from LIST_NODE and modified + uses of uniq_set in perfect.c and keylist.c. Due to changes + to Gen_Perf::compute_disjoint_sets this field was no longer + necessary, and its removal makes the program smaller and + potentially faster. + + * Added lots of changes/fixes suggested by Nels Olson + (umls.UUCP!olson@mis.ucsf.edu). In particular: + 1. Changed Bool_Array so that it would dynamically create + an array of unsigned shorts rather than ints if the + LO_CAL symbol was defined during program compilation. + This cuts the amount of dynamic memory usage in half, + which is important for large keyfile input. + 2. Added some additional debugging statements that print extra + info to stderr when the -d option is enabled. + 3. Fixed a really stupid bug in Key_List::print_switch + A right paren was placed at the wrong location, which broke + strlen (). + 4. Fixed a subtle problem with printing case values when keylinks + appear. The logic failed to account for the fact that there + can be keylinks *and* regular node info also! + 5. Changed the behavior of Key_List::read_keys so that it would + honor -D unequivocally, i.e., it doesn't try to turn off dup + handling if the user requests it, even if there are no + immediate links in the keyfile input. + 6. Modified the -j option so that -j 0 means `try random values + when searching for a way to resolve collisions.' + 7. Added a field `num_done' to the Gen_Perf struct. This is used + to report information collected when trying to resolve + hash collisions. + 8. Modified the merge_sets algorithm to perform a disjoint + union of two multisets. This ensures that subsequent + processing in Gen_Perf::affect_prev doesn't + waste time trying to change an associated value that is + shared between two conflicting keywords. + 9. Modified Gen_Perf::affects_prev so that it doesn't try + random jump values unless the -j 0 option is enabled. + 10. Fixed a silly bug in Gen_Perf::change. This problem caused + gperf to seg fault when the -k* option was given and the + keyfile file had long keywords. + +Sun Oct 29 00:18:55 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Modified class-specific new operations for Read_Line and + List_Node so they don't fail if SIZE is larger than twice + the previous buffer size. Note we double buffer size + everytime the previous buffer runs out, as a heuristic + to reduce future calls to malloc. + +Sun Oct 22 13:49:43 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Updated gperf version number to 2.0. Send to Doug Lea for + incorporation into the long-awaited `official' libg++ 1.36 + release! + + * Thanks to Nels Olson a silly bug in Gen_Perf::change () + was fixed. This problem caused gperf to seg fault when + the -k* option was given and the keyfile file had long + keywords. + + * Modified Key_List::print_hash_function so that it output + max_hash_value + 1 (rather than just max_hash_value) for + any associated value entries that don't correspond to + keyword charset characters. This should speed up rejection + of non-keyword strings a little in some cases. + +Sat Oct 21 19:28:36 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Fixed Key_List::print_hash_function so that it no longer output + things like `return 0 + ...' Although this probably gets + optimized away by even the worst C compilers there isn't any + point tempting fate... ;-) + + * Fixed class List_Node's constructor so that it wouldn't a priori + refuse to consider trying to hash keys whose length is less + than the smallest user-specified key position. It turns out + this is not a problem unless the user also specifies the -n + (NOLENGTH) option, in which case such keys most likely + don't have a prayer of being hashed correctly! + + * Changed the name of the generated lookup table from `Hash_Table' + to `asso_value' to be consistent with the gperf paper. + +Tue Oct 17 14:19:48 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added a flag GATHER_STATISTICS in the Makefile. If defined + during compilation this turns on certain collection facilities + that track the performance of gperf during its execution. In + particular, I want to see how many collisions occur for the + double hashing Hash_Table. + + * Added a safety check so that we don't screw up if the total + number of `resets' of the Bool_Array exceeds MAX_INT. Since + this number is around 2^31 it is unlikely that this would ever + occur for most input, but why take the risk? + + * Changed the behavior for the -a (ANSI) option so that the + generated prototypes use int rather than size_t for the LEN + parameter. It was too ugly having to #include all + over the place... + +Mon Oct 16 11:00:35 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Continued to work on the gperf paper for the USENIX C++ + conference. At some point this will be merged back into + the gperf documentation... + +Sat Oct 14 20:29:43 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Added a majorly neat hack to Bool_Array, suggested by rfg. + The basic idea was to throw away the Ullman array technique. + The Ullman array was used to remove the need to reinitialize all + the Bool_Array elements to zero everytime we needed to determine + whether there were duplicate hash values in the keyword list. + The current trick uses an `iteration number' scheme, which takes + about 1/3 the space and reduces the overall program running a + time by about 20 percent for large input! The hack works as + follows: + + 1. Dynamically allocation 1 boolean array of size k. + 2. Initialize the boolean array to zeros, and consider the first + iteration to be iteration 1. + 2. Then on all subsequent iterations we `reset' the bool array by + kicking the iteration count by 1. + 3. When it comes time to check whether a hash value is currently + in the boolean array we simply check its index location. If + the value stored there is *not* equal to the current iteration + number then the item is clearly *not* in the set. In that + case we assign the iteration number to that array's index + location for future reference. Otherwise, if the item at + the index location *is* equal to the iteration number we've + found a duplicate. No muss, no fuss! + +Mon Oct 2 12:30:54 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Changed some consts in options.h to enumerals, since g++ + doesn't seem to like them at the moment! + +Sat Sep 30 12:55:24 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Fixed a stupid bug in Key_List::print_hash_function that manifested + itself if the `-k$' option was given (i.e., only use the key[length] + character in the hash function). + + * Added support for the -C option. This makes the contents of + all generated tables `readonly'. + + * Changed the handling of generated switches so that there is + only one call to str[n]?cmp. This *greatly* reduces the size of + the generated assembly code on all compilers I've seen. + + * Fixed a subtle bug that occurred when the -l and -S option + was given. Code produced looked something like: + + if (len != key_len || !strcmp (s1, resword->name)) return resword; + + which doesn't make any sense. Clearly, this should be: + + if (len == key_len && !strcmp (s1, resword->name)) return resword; + +Tue Sep 26 10:36:50 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Changed class Read_Line's definition so that it no longer + needs to know about the buffering scheme used to speed up + dynamic memory allocation of input keywords and their + associated attributes. This means that operator new is no longer + a friend of Read_Line. + +Mon Sep 25 23:17:10 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Decided that Obstacks had too much overhead, so they were + removed in favor of super-efficient, low-overhead buffered + storage allocation hacks in Read_Line and List_Node. + + * No longer try to inline functions that g++ complains about + (Key_List::Merge and Key_List::Merge_Sort). + +Sun Sep 24 13:11:24 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Changed classes Read_Line and List_Node to use Obstacks in order + to cache memory allocation for keyword strings and List_Nodes. + + * Continued to experiment with inheritance schemes. + + * Added a new file `alpha.h', that declares static data shared + (i.e., inherited) between classes List_Node and Key_List. + +Tue Sep 12 16:14:41 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Made numerous changes to incorporate multiple inheritance in + gperf. + +Wed Aug 16 23:04:08 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added the -DCOMPILER_FIXED flag to the ./src/Makefile. This + implies that people trying to compile gperf need to have a + working version of the new g++ compiler (1.36.0). + + * Removed some extra spaces that were being added in the generated + C code. + +Mon Jul 24 17:09:46 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Fixed PRINT_HASH_FUNCTION and PRINT_LOOKUP_FUNCTION in keylist.c + so that the generated functions take an unsigned int length argument. + If -a is enabled the prototype is (const char *str, size_t len). + +Fri Jul 21 13:06:15 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Fixed a typo in PRINT_KEYWORD_TABLE in keylist.cc that prevented + the indentation from working correctly. + + * Fixed a horrible typo in PRINT_KEYWORD_TABLE in keylist.cc + that prevented links from being printed correctly. + +Tue Jul 18 16:04:31 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Fixed up readline.cc and readline.h so that they work OK + with g++ compilers that aren't completely up-to-date. + If symbol COMPILER_FIXED is defined then the behavior + that works on my more recent version of g++ is enabled. + +Sun Jul 9 17:53:28 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Changed the ./tests subdirectory Makefile so that it + uses $(CC) instead of gcc. + +Sun Jul 2 21:52:15 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Fixed a number of subtle bugs that occurred when -S was + combined with various and sundry options. + + * Added the -G option, that makes the generated keyword table + a global static variable, rather than hiding it inside + the lookup function. This allows other functions to directly + access the contents in this table. + + * Added the "#" feature, that allows comments inside the keyword + list from the input file. Comment handling takes place in readline.c. + This simplifies the code and reduces the number of malloc calls. + + * Also added the -H option (user can give the name of the hash + function) and the -T option (prevents the transfer of the type decl + to the output file, which is useful if the type is already defined + elsewhere). + +Thu Jun 22 20:39:39 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Modified many classes so that they would inherit Std_Err as + a base class. This makes things more abstract... + +Fri Jun 16 14:23:00 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Modified the -f (FAST) option. This now takes an argument. + The argument corresponds to the number of iterations used + to resolve collisions. -f 0 uses the length of the + keyword list (which is what -f did before). This makes + life much easier when dealing with large keyword files. + +Tue Jun 6 17:53:27 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added the -c (comparison) option. Enabling this + will use the strncmp function for string comparisons. + The default is to use strcmp. + + * Fixed a typo in key_list.cc (PRINT_SWITCH). This caused + faulty C code to be generated when the -D, -p, and -t + options were all enabled. + +Thu May 25 14:07:21 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Once again, changed class Read_Line to overload global operator + new. Hopefully, this will work...! + +Sun May 21 01:51:45 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Modified Key_List::print_hash_function () so that it properly + formats the associated values in the hash table according to + the maximum number of digits required to represent the largest + value. + + * Removed the named return value from class Hash_Table's + operator (), since this causes a seg fault when -O is enabled. + No sense tripping subtle g++ bugs if we don't have to.... ;-) + + * Removed the operator new hack from Read_Line, since this seemed + to create horrible bus error problems. + + * Changed many class member functions and data members to be `static', + if they don't manipulate this! + +Fri May 12 23:06:56 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Changed class Std_Err to use static member functions, a la + Ada or Modula 2. This eliminates the need for an explicit + error-handler class object. + + * Added the ``named return value'' feature to Hash_Table::operator () + and Bool_Array::operator [], just for the heck of it.... ;-) + + * Changed the previous hack in Read_Line so that we now use + the overloaded global `new' instead of NEW_STRING! + +Wed May 3 17:36:55 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Updated to version 1.7. This reflects the recent major changes + and the new C port. + + * Modified the GNU getopt.cc routine to have a class-based interface. + + * Fixed a typo in Perfect.cc ~Perfect that prevented the actual maximum + hash table size from being printed (maybe the stream classes + weren't so bad after all.... ;-). + + * Added support for the -f option. This generates the perfect + hash function ``fast.'' It reduces the execution time of + gperf, at the cost of minimizing the range of hash values. + +Tue May 2 16:23:29 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Added an efficiency hack to Read_Line. Instead of making + a call to operator NEW (a.k.a. malloc) for each input string + a new member function NEW_STRING stores a large buffer from + which new strings are carved out, growing the buffer if + necessary. It might be useful to add this throughout the + program.... + + * Removed all unnecessary calls to DELETE. If the program is about + to exit it is silly to waste time freeing memory. + + * Added the GNU getopt program to the distribution. This makes + GPERF portable to systems that don't include getopt in libc. + + * Added a strcspn member to class Key_List. This also increases + portability. + + * Added the get_include_src function from keylist.c as a member + function in class Key_List. Hopefully every function is + now associated with a class. This aids abstraction and + modularity. + + * Ported gperf to C. From now on both K&R C and GNU G++ versions + will be supported. There will be two ChangeLog files, one + for each version of the program. + +Mon May 1 16:41:45 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Fixed a bug with -k'*'. This now prints out *all* the cases + up to the length of the longest word in the keyword set. + +Sun Apr 30 12:15:25 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Removed all use of the stream classes. Too ugly, slow, and + not handled by the c++-mode formatter.... + + * Modified the handling of links (i.e., keywords that have + identical hash values as other keywords). This should + speed up hash function generation for keyword sets with + many duplicate entries. The trick is to treat duplicate + values as equivalence classes, so that each set of duplicate + values is represented only once in the main list processing. + + * Fixed some capitialization typos and indentations mistakes in + Key_List::print_hash_function. + +Sat Apr 29 12:04:03 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Fixed a typo/logico in Key_List::print_switch that prevented + the last keyword in the keyword list to be print out. This + requires further examination..... + + * Fixed a stupid bug in List_Node::List_node. If the -k'*' option + was enabled the KEY_SET string wasn't getting terminated with + '\0'! + +Fri Apr 28 12:38:35 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Renamed strexp.h and strexp.cc to iterator.h and iterator.cc. + Also changed the strexp class to iterator. Continued to work + on style... + + * Updated the version number to 1.6. This reflects all the + recent changes. + +Thu Apr 27 00:14:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added the -D option that properly handles keyword sets that + contain duplicate hash values. + + * Continued the stylistic changes. Added the #pragma once + directive to all the *.h files. Removed all #defines and + replaced them with static consts. Also moved the key_sort + routine from options.cc into the options class as a + member function. + +Mon Apr 3 13:26:55 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) + + * Made massive stylistic changes to bring source code into + conformance with GNU style guidelines. + +Thu Mar 30 23:28:45 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Fixed up the output routines so that they generate code + corresponding to the GNU style guidelines. + +Sat Mar 11 13:12:37 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Fixed Stderr constructors so that they wouldn't try to + use the base class initializer syntax for the static + class variable Program_Name. G++ 1.34 is stricter in + enforcing the rules! + +Fri Mar 10 11:24:14 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Removed -v and ``| more'' from the Makefile to keep rfg happy... + +Thu Mar 2 12:37:30 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Sent latest GNU gperf version 1.5 to Doug Lea for inclusion + into libg++ 1.34. Note that there is a small bug with + the new %{ ... %} source inclusion facility, since it doesn't + understand comments and will barf if %{ or %} appear nested + inside the outermost delimiters. This is too trivial of + a defect to fix at the moment... + +Tue Feb 28 11:19:58 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added the -K option, which allows the user to provide a + alternative name for the keyword structure component. + The default is still ``name.'' + + * Added the LEX and YACC-like ability to include arbitrary + text at the beginning of the generated C source code output. + This required two new functions Get_Special_Input, + Key_List::Save_Include_Src; + + * Fixed memory allocation bug in Key_List::Set_Types. + Variable Return_Type needs 1 additional location + to store the "*" if the -p option is used. + + * Added code to NULL terminate both Struct_Tag and Return_Type, + *after* the strncpy (stupid mistake). + +Mon Feb 27 14:39:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added a new option -N. This allows the user to specify the + name to be used for the generated lookup function. The + default name is still ``in_word_set.'' This makes it + possible to completely automate the perfect hash function + generation process! + +Mon Feb 20 23:33:14 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Corrected the Hash_Table::operator () function so that + *it* is responsible for deciding when a new key has the + same signature as a previously seen key. The key length + information is now used internally to this function to + decide whether to add to the hash table those keys with + the same key sets, but different lengths. Before, this + was handled by the Key_List::Read_Keys function. However, + this failed to work for certain duplicate keys, since + they weren't being entered into the hash table properly. + +Sun Feb 19 16:02:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Modified class Options by moving the enum Option_Type out + of the class. This is to satisfy the new enumeration + scope rules in C++. + +Sun Jan 15 15:12:09 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Incremented the version number upto 1.4 to reflect the new + options that affect the generated code. Send the new + distribution off to Michael for use with g++ 1.33. + + * Added a fix to Key_List::Read_Keys so that it checks for links + properly when the -n option is used. Previously, it didn't + catch obvious links, which caused it to spend large amount + of time searching for a solution that could never occur! + + * Modified the Key_List data structure to record *both* the + minimum and the maximum key lengths. This information + is now computed in Key_List::Read_Keys, and thus + Key_List::Print_Min_Max doesn't need to bother. + + * Modifed the key position iterator scheme in options.cc to + eliminate the need for member function Options::Advance. + Now, the Options::Get function performs the advancement + automatically, obviating the need for an extra function call. + + * Added the new function Options::Print_Options, to print out + the user-specified command line options to generated C + output file. + + * Added a new function, Key_List::Print_Keylength_Table, + which creates a table of lengths for use in speeding + up the keyword search. This also meant that a new + option, -l (LENTABLE) is recognized. It controls + whether the length table is printed and the comparison + made in the generated function ``in_word_set.'' + + * Added a comment at the top of the generated C code + output file that tells what version of gperf was used. + Next, I'll also dump out the command line options + as a comment too. Thanks to Michael Tiemann for the + feedback on this. + + * Fixed the -n option to make it work correctly with + other parts of the program (most notably the Perfect::Hash + function and the computation of minimum and maximum lengths. + +Fri Jan 13 21:25:27 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Realized the the need to add a test that will enable + optimziation of the generated C code in the ``hash'' function + by checking whether all the requested key positions are + guaranteed to exist due to the comparison in `in_word_set.'' + I'll put this in soon.... + +Thu Jan 12 20:09:21 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Added pascal, modula3, and modula2 tests inputs to the + Makefile + + * Recognised that there is a bug with the -n option. However + I'm too busy to fix it properly, right now. The problem + is that the generated #define end up being 0, since that's + my hack to make -n work. This needs complete rethinking! + +Tue Jan 10 00:08:16 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Added a new option, -n, that instructs gperf to not use the + length of an identifier when computing the hash functions. + I'm not sure how useful this is! + + * Retransmitted the distribution to rocky.oswego.edu. Hopefully, + this will work! + + * Began fixing the indentation and capitalization to conform + to the GNU coding guidelines. + +Mon Jan 9 22:23:18 1989 Doug Schmidt (schmidt at pompe.ics.uci.edu) + + * Fixed horrible bug in Read_Line::Readln_Aux. This was + a subtle and pernicous off-by-1 error, that overwrote + past the last character of the input string buffer. I + think this fault was killing the vax! + + * Yow, fixed an oversight in List_Node::List_Node, where the + pointer field Next was uninitialized. Luckily, the new routine + seems to return 0 filled objects the first time through! + +Sun Jan 8 13:43:14 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Modified the ``key linked'' diagnostic in Key_List::Read_Keys + to be more helpful and easy to read. + + * Fixed the List_Node::List_Node so that it would ignore trailing + fields if the -t option was not enabled. + + * Moved the List_Node declarations out of keylist.h and + into a file of its own, called listnode.cc and listnode.h + Made Set_Sort a member function of class List_Node. + + * Massively updated the documentation in the gperf.texinfo file. + + * Polished off the major revision to the print functions, + added a few new tests in the Makefile to check for the + validity of the program and ftp'ed the entire distribution + off to Doug Lea for libg++. ( changed it to + 1.3 to reflect the major changes with the generated + C code ). + + * Fixed Key_List::Print_Switch to deal with the -p and -t options. + This meant that the ``still-born'' function Key_List:: + Print_Type_Switch was superflous, so I removed it. + Also, removed the restriction in Option that the -p and + -t options couldn't be used simultaneously. + + * Modified List_Node::List_Node, to perform only 1 call to + ``new'' when dynamically allocating memory for the Key_Set + and the Uniq_Set. + +Sat Jan 7 14:10:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) + + * Fixed a big bug with the new policy of nesting the + wordlist inside of generated function ``in_word_set.'' + I'd forgotten to declare the wordlist array as static! + ( arrgh ). + + * Added a new function Key_List::Set_Types, that figures out + the return type for generated function ``in_word_set,'' + the user-defined ``struct tag,'' if one is used, and also + formates the array type for the static local array. + + * Changed the print routines to take advantage of the + new -p option. + + * Began adding the hooks to allow the return of a pointer + to a user defined struct location from the generated + ``in_word_set'' function instead of the current 0 or 1 + return value. Created function Key_List::Print_Type_Switch + and added option -p to class Option, allowing the user to + request generation of the aforementioned pointers returned + instead of booleans. + + * Put in checks in class Option to make sure that -S and -t + options are not used simultaneously. This restriction + will be removed in subsequent releases, once I decide on + a clean way to implement it. + + * Sent version 1.2 to Doug Lea for possible inclusion into + the libg++ distribution. + + * Moved the static word_list array inside the generated function + in_word_set. This supports better data hiding. + + * Added a texinfo file, gperf.texinfo + + * Revised the Makefile to cleanup the droppings from texinfo + and changed the name of gperf.cc and gperf.h to perfect.cc + and perfect.h. + +Fri Jan 6 13:04:45 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) + + * Implemented the switch statement output format. Much better + for large datasets in terms of space used. + + * Added new functions to break up the Key_List::Output function. + Functions added were Key_List::Print_Switch, Key_List::Print_Min_Max, + Key_List::Print_Keyword_Table, Key_List::Print_Hash_Function, + and Key_List::Print_Lookup_Function. This simplifies the + big mess in Key_List::Output considerably! + + * Added switch statement option to Options, which potentially + trades time for space in the generated lookup code. + +Thu Jan 5 22:46:34 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) + + * Released version 1.1 + + * Fixed a bug with Gperf::Merge_Set, it was skipping letters shared + between the Set_1 and Set_2. + + * Added the optimal min/max algorithm in Key_List::Output. This + runs in O ( 3n/2 ), rather than O ( 2n ) time. + + * Changed Gperf::Sort_Set to use insertion sort, rather than + bubble sort. + + * Added a check in Key_List::Output for the special case where + the keys used are 1,$. It is possible to generate more + efficient C code in this case. diff --git a/contrib/gperf-3.0.1/INSTALL b/contrib/gperf-3.0.1/INSTALL new file mode 100644 index 0000000000..350b32f513 --- /dev/null +++ b/contrib/gperf-3.0.1/INSTALL @@ -0,0 +1,183 @@ +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 a while. 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 code 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'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +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 + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. 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 `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +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. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + 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' + Use and 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. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--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. + diff --git a/contrib/gperf-3.0.1/Makefile.devel b/contrib/gperf-3.0.1/Makefile.devel new file mode 100644 index 0000000000..c47e26a43a --- /dev/null +++ b/contrib/gperf-3.0.1/Makefile.devel @@ -0,0 +1,44 @@ +# This is the developer's makefile, not the user's makefile. +# Don't use it unless you know exactly what you do! + +SHELL = /bin/sh +MAKE = make + +all : configures src/config.h.in src/config.h.msvc src/config.h_vms doc/gperf.1 + +CONFIGURES = configure lib/configure src/configure tests/configure doc/configure + +configures : $(CONFIGURES) + +configure : configure.in aclocal.m4 + autoconf -I . + +lib/configure : lib/configure.in aclocal.m4 + cd lib && autoconf -I .. + +src/configure : src/configure.in aclocal.m4 + cd src && autoconf -I .. + +tests/configure : tests/configure.in aclocal.m4 + cd tests && autoconf -I .. + +doc/configure : doc/configure.in aclocal.m4 + cd doc && autoconf -I .. + +check-configures : $(CONFIGURES) + set -e; for f in $(CONFIGURES); do bash -x -n $$f; done + +src/config.h.in : src/configure.in aclocal.m4 + cd src && autoheader -I .. + +src/config.h.msvc : src/config.h.in + cp src/config.h.in src/config.h.msvc + +src/config.h_vms : src/config.h.in + cp src/config.h.in src/config.h_vms + +doc/gperf.1 : force + prog=`PATH=build/src:src:$$PATH which gperf`; if test -n "$$prog"; then doc/help2man --name='generate a perfect hash function from a key set' --section=1 $$prog > doc/gperf.1; fi + +force : + diff --git a/contrib/gperf-3.0.1/NEWS b/contrib/gperf-3.0.1/NEWS new file mode 100644 index 0000000000..efa3ca0cc5 --- /dev/null +++ b/contrib/gperf-3.0.1/NEWS @@ -0,0 +1,80 @@ +New in 3.0.1: + +* Bug fix. + +New in 3.0: + +* Added option --output that allows to specify the output file name. +* Some options have been renamed: + --hash-fn-name=NAME --> --hash-function-name=NAME + --lookup-fn-name=NAME --> --lookup-function-name=NAME + --compare-strlen --> --compare-lengths + --global --> --global-table + The older variants are still supported for backward compatibility. +* The following options can now be specified inside the input file: + %delimiters=DELIMITER-LIST + %struct-type + %ignore-case + %language=LANGUAGE-NAME + %define slot-name NAME + %define initializer-suffix INITIALIZERS + %define hash-function-name NAME + %define lookup-function-name NAME + %define class-name NAME + %7bit + %compare-lengths + %compare-strncmp + %readonly-tables + %enum + %includes + %global-table + %pic + %define string-pool-name NAME + %null-strings + %define word-array-name NAME + %switch=COUNT + %omit-struct-type +* When the option -k is not given, the default key positions are now + computed depending on the set of keywords. +* If the input file is given by name, the output file will now contain + #line directives referring to the input file. +* Some keyword sets containing permutations, like { "xy", "yx", "xz", "zx" } + or { "abc", "acb", "bca", "cab" }, are now handled by gperf without + requiring the option -D. +* The generated table is usually much smaller than it was with earlier + versions of gperf. +* Added option -m/--multiple-iterations that allows to further reduce the + size of the generated table. +* When the search for a good hash function is not immediately successful, + the table's size will grow as needed. Earlier versions of gperf bailed + out with an "Internal error, duplicate hash code value". +* The options -f/--fast and -o/--occurrence-sort have no effect any more. +* Added options -P/--pic and --null-strings that optimize the generated code + for use in shared libraries. -P/--pic does a perfect optimization but may + require some small code changes (see the documentation for details), whereas + --null-strings does only a half-hearted optimization but works without + needing any change to surrounding code. +* Added option --ignore-case that produces a case independent lookup function. +* Bug fixes. + +New in 2.7.2: + +* Keywords may now be enclosed in double quotes; this permits the use of + '#', ',', space or NUL inside keywords. +* Bug fixes. + +New in 2.7.1: + +* Added option "-F" for gcc. + +New in 2.7: + +* gperf is now a stand-alone package, untied from libg++. +* Autoconfiguring. +* Removed the "-a" and "-g" options, extended the "-L" option instead. +* Removed the "-p" option, it is the default. +* Added long options ("--help", "--version" etc.). +* 8-bit cleanliness is now the default; use "-7" to get the old behaviour. +* Compiles with any C++ compiler. +* Numerous small improvements. + diff --git a/contrib/gperf-3.0.1/README b/contrib/gperf-3.0.1/README new file mode 100644 index 0000000000..26173bfc24 --- /dev/null +++ b/contrib/gperf-3.0.1/README @@ -0,0 +1,28 @@ +This is GNU gperf. It is a program that generates perfect hash +functions for sets of key words. A perfect hash function is: + + A hash function and a data structure that allows + recognition of a key word in a set of words using + exactly 1 probe into the data structure. + +The doc/gperf.html file explains how the program works, the form of +the input, what options are available, and hints on choosing the best +options for particular key words set. + +See the file NEWS for a list of major changes in the current release. + +See the file INSTALL for compilation and installation instructions. + +Output from the GPERF program is used to recognize reserved words in +the GNU C, GNU C++, and GNU Pascal compilers, as well as with the GNU +indent program. + +For general documentation on the coding and usage standards +this distribution follows, see the GNU standards document +ftp://ftp.gnu.org/pub/gnu/standards.*, especially the 'Makefile +Conventions', 'Configuration', and 'User Interfaces' sections. + +Mail suggestions and bug reports to . When +reporting bugs, please include in the subject line the package name +and version (output of 'gperf --version') for which you found a problem. + diff --git a/contrib/gperf-3.0.1/README.DELETED b/contrib/gperf-3.0.1/README.DELETED new file mode 100644 index 0000000000..81bb475dba --- /dev/null +++ b/contrib/gperf-3.0.1/README.DELETED @@ -0,0 +1,24 @@ +$DragonFly: src/contrib/gperf-3.0.1/Attic/README.DELETED,v 1.1.1.1 2005/04/21 18:16:32 asmodai Exp $ +*/*.dvi +*/*.html +*/*.info +*/*.ps +*/texinfo.tex +Makefile.in +Makefile.msvc +Makefile.vms +README.vms +README.woe32 +aclocal.m4 +configure +configure.in +doc/Makefile.in +doc/configure +doc/configure.in +doc/help2man +lib/Makefile.in +lib/configure +lib/configure.in +mkinstalldirs +src/Makefile.in +tests/ diff --git a/contrib/gperf-3.0.1/doc/gperf.1 b/contrib/gperf-3.0.1/doc/gperf.1 new file mode 100644 index 0000000000..d40b419e0b --- /dev/null +++ b/contrib/gperf-3.0.1/doc/gperf.1 @@ -0,0 +1,212 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23. +.TH GPERF "1" "June 2003" "GNU gperf 3.0.1" FSF +.SH NAME +gperf \- generate a perfect hash function from a key set +.SH SYNOPSIS +.B gperf +[\fIOPTION\fR]... [\fIINPUT-FILE\fR] +.SH DESCRIPTION +GNU 'gperf' generates perfect hash functions. +.PP +If a long option shows an argument as mandatory, then it is mandatory +for the equivalent short option also. +.SS "Output file location:" +.HP +\fB\-\-output\-file\fR=\fIFILE\fR Write output to specified file. +.PP +The results are written to standard output if no output file is specified +or if it is -. +.SS "Input file interpretation:" +.TP +\fB\-e\fR, \fB\-\-delimiters\fR=\fIDELIMITER\-LIST\fR +Allow user to provide a string containing delimiters +used to separate keywords from their attributes. +Default is ",". +.TP +\fB\-t\fR, \fB\-\-struct\-type\fR +Allows the user to include a structured type +declaration for generated code. Any text before %% +is considered part of the type declaration. Key +words and additional fields may follow this, one +group of fields per line. +.TP +\fB\-\-ignore\-case\fR +Consider upper and lower case ASCII characters as +equivalent. Note that locale dependent case mappings +are ignored. +.SS "Language for the output code:" +.TP +\fB\-L\fR, \fB\-\-language\fR=\fILANGUAGE\-NAME\fR +Generates code in the specified language. Languages +handled are currently C++, ANSI-C, C, and KR-C. The +default is C. +.SS "Details in the output code:" +.TP +\fB\-K\fR, \fB\-\-slot\-name\fR=\fINAME\fR +Select name of the keyword component in the keyword +structure. +.TP +\fB\-F\fR, \fB\-\-initializer\-suffix\fR=\fIINITIALIZERS\fR +Initializers for additional components in the keyword +structure. +.TP +\fB\-H\fR, \fB\-\-hash\-function\-name\fR=\fINAME\fR +Specify name of generated hash function. Default is +\&'hash'. +.TP +\fB\-N\fR, \fB\-\-lookup\-function\-name\fR=\fINAME\fR +Specify name of generated lookup function. Default +name is 'in_word_set'. +.TP +\fB\-Z\fR, \fB\-\-class\-name\fR=\fINAME\fR +Specify name of generated C++ class. Default name is +\&'Perfect_Hash'. +.TP +\fB\-7\fR, \fB\-\-seven\-bit\fR +Assume 7-bit characters. +.TP +\fB\-l\fR, \fB\-\-compare\-lengths\fR +Compare key lengths before trying a string +comparison. This is necessary if the keywords +contain NUL bytes. It also helps cut down on the +number of string comparisons made during the lookup. +.TP +\fB\-c\fR, \fB\-\-compare\-strncmp\fR +Generate comparison code using strncmp rather than +strcmp. +.TP +\fB\-C\fR, \fB\-\-readonly\-tables\fR +Make the contents of generated lookup tables +constant, i.e., readonly. +.TP +\fB\-E\fR, \fB\-\-enum\fR +Define constant values using an enum local to the +lookup function rather than with defines. +.TP +\fB\-I\fR, \fB\-\-includes\fR +Include the necessary system include file +at the beginning of the code. +.TP +\fB\-G\fR, \fB\-\-global\-table\fR +Generate the static table of keywords as a static +global variable, rather than hiding it inside of the +lookup function (which is the default behavior). +.TP +\fB\-P\fR, \fB\-\-pic\fR +Optimize the generated table for inclusion in shared +libraries. This reduces the startup time of programs +using a shared library containing the generated code. +.TP +\fB\-Q\fR, \fB\-\-string\-pool\-name\fR=\fINAME\fR +Specify name of string pool generated by option \fB\-\-pic\fR. +Default name is 'stringpool'. +.TP +\fB\-\-null\-strings\fR +Use NULL strings instead of empty strings for empty +keyword table entries. +.TP +\fB\-W\fR, \fB\-\-word\-array\-name\fR=\fINAME\fR +Specify name of word list array. Default name is +\&'wordlist'. +.TP +\fB\-S\fR, \fB\-\-switch\fR=\fICOUNT\fR +Causes the generated C code to use a switch +statement scheme, rather than an array lookup table. +This can lead to a reduction in both time and space +requirements for some keyfiles. The COUNT argument +determines how many switch statements are generated. +A value of 1 generates 1 switch containing all the +elements, a value of 2 generates 2 tables with 1/2 +the elements in each table, etc. If COUNT is very +large, say 1000000, the generated C code does a +binary search. +.TP +\fB\-T\fR, \fB\-\-omit\-struct\-type\fR +Prevents the transfer of the type declaration to the +output file. Use this option if the type is already +defined elsewhere. +.SS "Algorithm employed by gperf:" +.TP +\fB\-k\fR, \fB\-\-key\-positions\fR=\fIKEYS\fR +Select the key positions used in the hash function. +The allowable choices range between 1-255, inclusive. +The positions are separated by commas, ranges may be +used, and key positions may occur in any order. +Also, the meta-character '*' causes the generated +hash function to consider ALL key positions, and $ +indicates the "final character" of a key, e.g., +$,1,2,4,6-10. +.TP +\fB\-D\fR, \fB\-\-duplicates\fR +Handle keywords that hash to duplicate values. This +is useful for certain highly redundant keyword sets. +.TP +\fB\-m\fR, \fB\-\-multiple\-iterations\fR=\fIITERATIONS\fR +Perform multiple choices of the \fB\-i\fR and \fB\-j\fR values, +and choose the best results. This increases the +running time by a factor of ITERATIONS but does a +good job minimizing the generated table size. +.TP +\fB\-i\fR, \fB\-\-initial\-asso\fR=\fIN\fR +Provide an initial value for the associate values +array. Default is 0. Setting this value larger helps +inflate the size of the final table. +.TP +\fB\-j\fR, \fB\-\-jump\fR=\fIJUMP\-VALUE\fR +Affects the "jump value", i.e., how far to advance +the associated character value upon collisions. Must +be an odd number, default is 5. +.TP +\fB\-n\fR, \fB\-\-no\-strlen\fR +Do not include the length of the keyword when +computing the hash function. +.TP +\fB\-r\fR, \fB\-\-random\fR +Utilizes randomness to initialize the associated +values table. +.TP +\fB\-s\fR, \fB\-\-size\-multiple\fR=\fIN\fR +Affects the size of the generated hash table. The +numeric argument N indicates "how many times larger +or smaller" the associated value range should be, +in relationship to the number of keys, e.g. a value +of 3 means "allow the maximum associated value to +be about 3 times larger than the number of input +keys". Conversely, a value of 1/3 means "make the +maximum associated value about 3 times smaller than +the number of input keys". A larger table should +decrease the time required for an unsuccessful +search, at the expense of extra table space. Default +value is 1. +.SS "Informative output:" +.TP +\fB\-h\fR, \fB\-\-help\fR +Print this message. +.TP +\fB\-v\fR, \fB\-\-version\fR +Print the gperf version number. +.TP +\fB\-d\fR, \fB\-\-debug\fR +Enables the debugging option (produces verbose +output to the standard error). +.SH AUTHOR +Written by Douglas C. Schmidt and Bruno Haible. +.SH "REPORTING BUGS" +Report bugs to . +.SH COPYRIGHT +Copyright \(co 1989-1998, 2000-2003 Free Software Foundation, Inc. +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH "SEE ALSO" +The full documentation for +.B gperf +is maintained as a Texinfo manual. If the +.B info +and +.B gperf +programs are properly installed at your site, the command +.IP +.B info gperf +.PP +should give you access to the complete manual. diff --git a/contrib/gperf-3.0.1/doc/gperf.texi b/contrib/gperf-3.0.1/doc/gperf.texi new file mode 100644 index 0000000000..b280e55161 --- /dev/null +++ b/contrib/gperf-3.0.1/doc/gperf.texi @@ -0,0 +1,1356 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setfilename gperf.info +@settitle Perfect Hash Function Generator +@c @setchapternewpage odd +@c %**end of header + +@c some day we should @include version.texi instead of defining +@c these values at hand. +@set UPDATED 12 June 2003 +@set EDITION 3.0.1 +@set VERSION 3.0.1 +@c --------------------- + +@c remove the black boxes generated in the GPL appendix. +@finalout + +@c Merge functions into the concept index +@syncodeindex fn cp +@c @synindex pg cp + +@dircategory Programming Tools +@direntry +* Gperf: (gperf). Perfect Hash Function Generator. +@end direntry + +@ifinfo +This file documents the features of the GNU Perfect Hash Function +Generator @value{VERSION}. + +Copyright @copyright{} 1989-2003 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 a 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 also that the +section entitled ``GNU General Public License'' is included exactly as +in the original, and 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 the section entitled ``GNU General Public License'' and this +permission notice may be included in translations approved by the Free +Software Foundation instead of in the original English. + +@end ifinfo + +@titlepage +@title User's Guide to @code{gperf} @value{VERSION} +@subtitle The GNU Perfect Hash Function Generator +@subtitle Edition @value{EDITION}, @value{UPDATED} +@author Douglas C. Schmidt +@author Bruno Haible + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1989-2003 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 also that the +section entitled ``GNU General Public License'' is included +exactly as in the original, and 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 the section entitled ``GNU General Public License'' may be +included in a translation approved by the author instead of in the +original English. +@end titlepage + +@ifinfo +@node Top, Copying, (dir), (dir) +@top Introduction + +This manual documents the GNU @code{gperf} perfect hash function generator +utility, focusing on its features and how to use them, and how to report +bugs. + +@menu +* Copying:: GNU @code{gperf} General Public License says + how you can copy and share @code{gperf}. +* Contributors:: People who have contributed to @code{gperf}. +* Motivation:: The purpose of @code{gperf}. +* Search Structures:: Static search structures and GNU @code{gperf} +* Description:: High-level discussion of how GPERF functions. +* Options:: A description of options to the program. +* Bugs:: Known bugs and limitations with GPERF. +* Projects:: Things still left to do. +* Bibliography:: Material Referenced in this Report. + +* Concept Index:: + +@detailmenu --- The Detailed Node Listing --- + +High-Level Description of GNU @code{gperf} + +* Input Format:: Input Format to @code{gperf} +* Output Format:: Output Format for Generated C Code with @code{gperf} +* Binary Strings:: Use of NUL bytes + +Input Format to @code{gperf} + +* Declarations:: Declarations. +* Keywords:: Format for Keyword Entries. +* Functions:: Including Additional C Functions. +* Controls for GNU indent:: Where to place directives for GNU @code{indent}. + +Declarations + +* User-supplied Struct:: Specifying keywords with attributes. +* Gperf Declarations:: Embedding command line options in the input. +* C Code Inclusion:: Including C declarations and definitions. + +Invoking @code{gperf} + +* Input Details:: Options that affect Interpretation of the Input File +* Output Language:: Specifying the Language for the Output Code +* Output Details:: Fine tuning Details in the Output Code +* Algorithmic Details:: Changing the Algorithms employed by @code{gperf} +* Verbosity:: Informative Output + +@end detailmenu +@end menu + +@end ifinfo + +@node Copying, Contributors, Top, Top +@unnumbered GNU GENERAL PUBLIC LICENSE +@include gpl.texinfo + +@node Contributors, Motivation, Copying, Top +@unnumbered Contributors to GNU @code{gperf} Utility + +@itemize @bullet +@item +@cindex Bugs +The GNU @code{gperf} perfect hash function generator utility was +written in GNU C++ by Douglas C. Schmidt. The general +idea for the perfect hash function generator was inspired by Keith +Bostic's algorithm written in C, and distributed to net.sources around +1984. The current program is a heavily modified, enhanced, and extended +implementation of Keith's basic idea, created at the University of +California, Irvine. Bugs, patches, and suggestions should be reported +to @code{}. + +@item +Special thanks is extended to Michael Tiemann and Doug Lea, for +providing a useful compiler, and for giving me a forum to exhibit my +creation. + +In addition, Adam de Boor and Nels Olson provided many tips and insights +that greatly helped improve the quality and functionality of @code{gperf}. + +@item +Bruno Haible enhanced and optimized the search algorithm. He also rewrote +the input routines and the output routines for better reliability, and +added a testsuite. +@end itemize + +@node Motivation, Search Structures, Contributors, Top +@chapter Introduction + +@code{gperf} is a perfect hash function generator written in C++. It +transforms an @var{n} element user-specified keyword set @var{W} into a +perfect hash function @var{F}. @var{F} uniquely maps keywords in +@var{W} onto the range 0..@var{k}, where @var{k} >= @var{n-1}. If @var{k} += @var{n-1} then @var{F} is a @emph{minimal} perfect hash function. +@code{gperf} generates a 0..@var{k} element static lookup table and a +pair of C functions. These functions determine whether a given +character string @var{s} occurs in @var{W}, using at most one probe into +the lookup table. + +@code{gperf} currently generates the reserved keyword recognizer for +lexical analyzers in several production and research compilers and +language processing tools, including GNU C, GNU C++, GNU Java, GNU Pascal, +GNU Modula 3, and GNU indent. Complete C++ source code for @code{gperf} is +available from @code{http://ftp.gnu.org/pub/gnu/gperf/}. +A paper describing @code{gperf}'s design and implementation in greater +detail is available in the Second USENIX C++ Conference proceedings +or from @code{http://www.cs.wustl.edu/~schmidt/resume.html}. + +@node Search Structures, Description, Motivation, Top +@chapter Static search structures and GNU @code{gperf} +@cindex Static search structure + +A @dfn{static search structure} is an Abstract Data Type with certain +fundamental operations, e.g., @emph{initialize}, @emph{insert}, +and @emph{retrieve}. Conceptually, all insertions occur before any +retrievals. In practice, @code{gperf} generates a @emph{static} array +containing search set keywords and any associated attributes specified +by the user. Thus, there is essentially no execution-time cost for the +insertions. It is a useful data structure for representing @emph{static +search sets}. Static search sets occur frequently in software system +applications. Typical static search sets include compiler reserved +words, assembler instruction opcodes, and built-in shell interpreter +commands. Search set members, called @dfn{keywords}, are inserted into +the structure only once, usually during program initialization, and are +not generally modified at run-time. + +Numerous static search structure implementations exist, e.g., +arrays, linked lists, binary search trees, digital search tries, and +hash tables. Different approaches offer trade-offs between space +utilization and search time efficiency. For example, an @var{n} element +sorted array is space efficient, though the average-case time +complexity for retrieval operations using binary search is +proportional to log @var{n}. Conversely, hash table implementations +often locate a table entry in constant time, but typically impose +additional memory overhead and exhibit poor worst case performance. + +@cindex Minimal perfect hash functions +@emph{Minimal perfect hash functions} provide an optimal solution for a +particular class of static search sets. A minimal perfect hash +function is defined by two properties: + +@itemize @bullet +@item +It allows keyword recognition in a static search set using at most +@emph{one} probe into the hash table. This represents the ``perfect'' +property. +@item +The actual memory allocated to store the keywords is precisely large +enough for the keyword set, and @emph{no larger}. This is the +``minimal'' property. +@end itemize + +For most applications it is far easier to generate @emph{perfect} hash +functions than @emph{minimal perfect} hash functions. Moreover, +non-minimal perfect hash functions frequently execute faster than +minimal ones in practice. This phenomena occurs since searching a +sparse keyword table increases the probability of locating a ``null'' +entry, thereby reducing string comparisons. @code{gperf}'s default +behavior generates @emph{near-minimal} perfect hash functions for +keyword sets. However, @code{gperf} provides many options that permit +user control over the degree of minimality and perfection. + +Static search sets often exhibit relative stability over time. For +example, Ada's 63 reserved words have remained constant for nearly a +decade. It is therefore frequently worthwhile to expend concerted +effort building an optimal search structure @emph{once}, if it +subsequently receives heavy use multiple times. @code{gperf} removes +the drudgery associated with constructing time- and space-efficient +search structures by hand. It has proven a useful and practical tool +for serious programming projects. Output from @code{gperf} is currently +used in several production and research compilers, including GNU C, GNU +C++, GNU Java, GNU Pascal, and GNU Modula 3. The latter two compilers are +not yet part of the official GNU distribution. Each compiler utilizes +@code{gperf} to automatically generate static search structures that +efficiently identify their respective reserved keywords. + +@node Description, Options, Search Structures, Top +@chapter High-Level Description of GNU @code{gperf} + +@menu +* Input Format:: Input Format to @code{gperf} +* Output Format:: Output Format for Generated C Code with @code{gperf} +* Binary Strings:: Use of NUL bytes +@end menu + +The perfect hash function generator @code{gperf} reads a set of +``keywords'' from an input file (or from the standard input by +default). It attempts to derive a perfect hashing function that +recognizes a member of the @dfn{static keyword set} with at most a +single probe into the lookup table. If @code{gperf} succeeds in +generating such a function it produces a pair of C source code routines +that perform hashing and table lookup recognition. All generated C code +is directed to the standard output. Command-line options described +below allow you to modify the input and output format to @code{gperf}. + +By default, @code{gperf} attempts to produce time-efficient code, with +less emphasis on efficient space utilization. However, several options +exist that permit trading-off execution time for storage space and vice +versa. In particular, expanding the generated table size produces a +sparse search structure, generally yielding faster searches. +Conversely, you can direct @code{gperf} to utilize a C @code{switch} +statement scheme that minimizes data space storage size. Furthermore, +using a C @code{switch} may actually speed up the keyword retrieval time +somewhat. Actual results depend on your C compiler, of course. + +In general, @code{gperf} assigns values to the bytes it is using +for hashing until some set of values gives each keyword a unique value. +A helpful heuristic is that the larger the hash value range, the easier +it is for @code{gperf} to find and generate a perfect hash function. +Experimentation is the key to getting the most from @code{gperf}. + +@node Input Format, Output Format, Description, Description +@section Input Format to @code{gperf} +@cindex Format +@cindex Declaration section +@cindex Keywords section +@cindex Functions section +You can control the input file format by varying certain command-line +arguments, in particular the @samp{-t} option. The input's appearance +is similar to GNU utilities @code{flex} and @code{bison} (or UNIX +utilities @code{lex} and @code{yacc}). Here's an outline of the general +format: + +@example +@group +declarations +%% +keywords +%% +functions +@end group +@end example + +@emph{Unlike} @code{flex} or @code{bison}, the declarations section and +the functions section are optional. The following sections describe the +input format for each section. + +@menu +* Declarations:: Declarations. +* Keywords:: Format for Keyword Entries. +* Functions:: Including Additional C Functions. +* Controls for GNU indent:: Where to place directives for GNU @code{indent}. +@end menu + +It is possible to omit the declaration section entirely, if the @samp{-t} +option is not given. In this case the input file begins directly with the +first keyword line, e.g.: + +@example +@group +january +february +march +april +... +@end group +@end example + +@node Declarations, Keywords, Input Format, Input Format +@subsection Declarations + +The keyword input file optionally contains a section for including +arbitrary C declarations and definitions, @code{gperf} declarations that +act like command-line options, as well as for providing a user-supplied +@code{struct}. + +@menu +* User-supplied Struct:: Specifying keywords with attributes. +* Gperf Declarations:: Embedding command line options in the input. +* C Code Inclusion:: Including C declarations and definitions. +@end menu + +@node User-supplied Struct, Gperf Declarations, Declarations, Declarations +@subsubsection User-supplied @code{struct} + +If the @samp{-t} option (or, equivalently, the @samp{%struct-type} declaration) +@emph{is} enabled, you @emph{must} provide a C @code{struct} as the last +component in the declaration section from the input file. The first +field in this struct must be of type @code{char *} or @code{const char *} +if the @samp{-P} option is not given, or of type @code{int} if the option +@samp{-P} (or, equivalently, the @samp{%pic} declaration) is enabled. +This first field must be called @samp{name}, although it is possible to modify +its name with the @samp{-K} option (or, equivalently, the +@samp{%define slot-name} declaration) described below. + +Here is a simple example, using months of the year and their attributes as +input: + +@example +@group +struct month @{ char *name; int number; int days; int leap_days; @}; +%% +january, 1, 31, 31 +february, 2, 28, 29 +march, 3, 31, 31 +april, 4, 30, 30 +may, 5, 31, 31 +june, 6, 30, 30 +july, 7, 31, 31 +august, 8, 31, 31 +september, 9, 30, 30 +october, 10, 31, 31 +november, 11, 30, 30 +december, 12, 31, 31 +@end group +@end example + +@cindex @samp{%%} +Separating the @code{struct} declaration from the list of keywords and +other fields are a pair of consecutive percent signs, @samp{%%}, +appearing left justified in the first column, as in the UNIX utility +@code{lex}. + +If the @code{struct} has already been declared in an include file, it can +be mentioned in an abbreviated form, like this: + +@example +@group +struct month; +%% +january, 1, 31, 31 +... +@end group +@end example + +@node Gperf Declarations, C Code Inclusion, User-supplied Struct, Declarations +@subsubsection Gperf Declarations + +The declaration section can contain @code{gperf} declarations. They +influence the way @code{gperf} works, like command line options do. +In fact, every such declaration is equivalent to a command line option. +There are three forms of declarations: + +@enumerate +@item +Declarations without argument, like @samp{%compare-lengths}. + +@item +Declarations with an argument, like @samp{%switch=@var{count}}. + +@item +Declarations of names of entities in the output file, like +@samp{%define lookup-function-name @var{name}}. +@end enumerate + +When a declaration is given both in the input file and as a command line +option, the command-line option's value prevails. + +The following @code{gperf} declarations are available. + +@table @samp +@item %delimiters=@var{delimiter-list} +@cindex @samp{%delimiters} +Allows you to provide a string containing delimiters used to +separate keywords from their attributes. The default is ",". This +option is essential if you want to use keywords that have embedded +commas or newlines. + +@item %struct-type +@cindex @samp{%struct-type} +Allows you to include a @code{struct} type declaration for generated +code; see above for an example. + +@item %ignore-case +@cindex @samp{%ignore-case} +Consider upper and lower case ASCII characters as equivalent. The string +comparison will use a case insignificant character comparison. Note that +locale dependent case mappings are ignored. + +@item %language=@var{language-name} +@cindex @samp{%language} +Instructs @code{gperf} to generate code in the language specified by the +option's argument. Languages handled are currently: + +@table @samp +@item KR-C +Old-style K&R C. This language is understood by old-style C compilers and +ANSI C compilers, but ANSI C compilers may flag warnings (or even errors) +because of lacking @samp{const}. + +@item C +Common C. This language is understood by ANSI C compilers, and also by +old-style C compilers, provided that you @code{#define const} to empty +for compilers which don't know about this keyword. + +@item ANSI-C +ANSI C. This language is understood by ANSI C compilers and C++ compilers. + +@item C++ +C++. This language is understood by C++ compilers. +@end table + +The default is C. + +@item %define slot-name @var{name} +@cindex @samp{%define slot-name} +This declaration is only useful when option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) has been given. +By default, the program assumes the structure component identifier for +the keyword is @samp{name}. This option allows an arbitrary choice of +identifier for this component, although it still must occur as the first +field in your supplied @code{struct}. + +@item %define initializer-suffix @var{initializers} +@cindex @samp{%define initializer-suffix} +This declaration is only useful when option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) has been given. +It permits to specify initializers for the structure members following +@var{slot-name} in empty hash table entries. The list of initializers +should start with a comma. By default, the emitted code will +zero-initialize structure members following @var{slot-name}. + +@item %define hash-function-name @var{name} +@cindex @samp{%define hash-function-name} +Allows you to specify the name for the generated hash function. Default +name is @samp{hash}. This option permits the use of two hash tables in +the same file. + +@item %define lookup-function-name @var{name} +@cindex @samp{%define lookup-function-name} +Allows you to specify the name for the generated lookup function. +Default name is @samp{in_word_set}. This option permits multiple +generated hash functions to be used in the same application. + +@item %define class-name @var{name} +@cindex @samp{%define class-name} +This option is only useful when option @samp{-L C++} (or, equivalently, +the @samp{%language=C++} declaration) has been given. It +allows you to specify the name of generated C++ class. Default name is +@code{Perfect_Hash}. + +@item %7bit +@cindex @samp{%7bit} +This option specifies that all strings that will be passed as arguments +to the generated hash function and the generated lookup function will +solely consist of 7-bit ASCII characters (bytes in the range 0..127). +(Note that the ANSI C functions @code{isalnum} and @code{isgraph} do +@emph{not} guarantee that a byte is in this range. Only an explicit +test like @samp{c >= 'A' && c <= 'Z'} guarantees this.) + +@item %compare-lengths +@cindex @samp{%compare-lengths} +Compare keyword lengths before trying a string comparison. This option +is mandatory for binary comparisons (@pxref{Binary Strings}). It also might +cut down on the number of string comparisons made during the lookup, since +keywords with different lengths are never compared via @code{strcmp}. +However, using @samp{%compare-lengths} might greatly increase the size of the +generated C code if the lookup table range is large (which implies that +the switch option @samp{-S} or @samp{%switch} is not enabled), since the length +table contains as many elements as there are entries in the lookup table. + +@item %compare-strncmp +@cindex @samp{%compare-strncmp} +Generates C code that uses the @code{strncmp} function to perform +string comparisons. The default action is to use @code{strcmp}. + +@item %readonly-tables +@cindex @samp{%readonly-tables} +Makes the contents of all generated lookup tables constant, i.e., +``readonly''. Many compilers can generate more efficient code for this +by putting the tables in readonly memory. + +@item %enum +@cindex @samp{%enum} +Define constant values using an enum local to the lookup function rather +than with #defines. This also means that different lookup functions can +reside in the same file. Thanks to James Clark @code{}. + +@item %includes +@cindex @samp{%includes} +Include the necessary system include file, @code{}, at the +beginning of the code. By default, this is not done; the user must +include this header file himself to allow compilation of the code. + +@item %global-table +@cindex @samp{%global-table} +Generate the static table of keywords as a static global variable, +rather than hiding it inside of the lookup function (which is the +default behavior). + +@item %pic +@cindex @samp{%pic} +Optimize the generated table for inclusion in shared libraries. This +reduces the startup time of programs using a shared library containing +the generated code. If the @samp{%struct-type} declaration (or, +equivalently, the option @samp{-t}) is also given, the first field of the +user-defined struct must be of type @samp{int}, not @samp{char *}, because +it will contain offsets into the string pool instead of actual strings. +To convert such an offset to a string, you can use the expression +@samp{stringpool + @var{o}}, where @var{o} is the offset. The string pool +name can be changed through the @samp{%define string-pool-name} declaration. + +@item %define string-pool-name @var{name} +@cindex @samp{%define string-pool-name} +Allows you to specify the name of the generated string pool created by +the declaration @samp{%pic} (or, equivalently, the option @samp{-P}). +The default name is @samp{stringpool}. This declaration permits the use of +two hash tables in the same file, with @samp{%pic} and even when the +@samp{%global-table} declaration (or, equivalently, the option @samp{-G}) +is given. + +@item %null-strings +@cindex @samp{%null-strings} +Use NULL strings instead of empty strings for empty keyword table entries. +This reduces the startup time of programs using a shared library containing +the generated code (but not as much as the declaration @samp{%pic}), at the +expense of one more test-and-branch instruction at run time. + +@item %define word-array-name @var{name} +@cindex @samp{%define word-array-name} +Allows you to specify the name for the generated array containing the +hash table. Default name is @samp{wordlist}. This option permits the +use of two hash tables in the same file, even when the option @samp{-G} +(or, equivalently, the @samp{%global-table} declaration) is given. + +@item %switch=@var{count} +@cindex @samp{%switch} +Causes the generated C code to use a @code{switch} statement scheme, +rather than an array lookup table. This can lead to a reduction in both +time and space requirements for some input files. The argument to this +option determines how many @code{switch} statements are generated. A +value of 1 generates 1 @code{switch} containing all the elements, a +value of 2 generates 2 tables with 1/2 the elements in each +@code{switch}, etc. This is useful since many C compilers cannot +correctly generate code for large @code{switch} statements. This option +was inspired in part by Keith Bostic's original C program. + +@item %omit-struct-type +@cindex @samp{%omit-struct-type} +Prevents the transfer of the type declaration to the output file. Use +this option if the type is already defined elsewhere. +@end table + +@node C Code Inclusion, , Gperf Declarations, Declarations +@subsubsection C Code Inclusion + +@cindex @samp{%@{} +@cindex @samp{%@}} +Using a syntax similar to GNU utilities @code{flex} and @code{bison}, it +is possible to directly include C source text and comments verbatim into +the generated output file. This is accomplished by enclosing the region +inside left-justified surrounding @samp{%@{}, @samp{%@}} pairs. Here is +an input fragment based on the previous example that illustrates this +feature: + +@example +@group +%@{ +#include +/* This section of code is inserted directly into the output. */ +int return_month_days (struct month *months, int is_leap_year); +%@} +struct month @{ char *name; int number; int days; int leap_days; @}; +%% +january, 1, 31, 31 +february, 2, 28, 29 +march, 3, 31, 31 +... +@end group +@end example + +@node Keywords, Functions, Declarations, Input Format +@subsection Format for Keyword Entries + +The second input file format section contains lines of keywords and any +associated attributes you might supply. A line beginning with @samp{#} +in the first column is considered a comment. Everything following the +@samp{#} is ignored, up to and including the following newline. A line +beginning with @samp{%} in the first column is an option declaration and +must not occur within the keywords section. + +The first field of each non-comment line is always the keyword itself. It +can be given in two ways: as a simple name, i.e., without surrounding +string quotation marks, or as a string enclosed in double-quotes, in +C syntax, possibly with backslash escapes like @code{\"} or @code{\234} +or @code{\xa8}. In either case, it must start right at the beginning +of the line, without leading whitespace. +In this context, a ``field'' is considered to extend up to, but +not include, the first blank, comma, or newline. Here is a simple +example taken from a partial list of C reserved words: + +@example +@group +# These are a few C reserved words, see the c.gperf file +# for a complete list of ANSI C reserved words. +unsigned +sizeof +switch +signed +if +default +for +while +return +@end group +@end example + +Note that unlike @code{flex} or @code{bison} the first @samp{%%} marker +may be elided if the declaration section is empty. + +Additional fields may optionally follow the leading keyword. Fields +should be separated by commas, and terminate at the end of line. What +these fields mean is entirely up to you; they are used to initialize the +elements of the user-defined @code{struct} provided by you in the +declaration section. If the @samp{-t} option (or, equivalently, the +@samp{%struct-type} declaration) is @emph{not} enabled +these fields are simply ignored. All previous examples except the last +one contain keyword attributes. + +@node Functions, Controls for GNU indent, Keywords, Input Format +@subsection Including Additional C Functions + +The optional third section also corresponds closely with conventions +found in @code{flex} and @code{bison}. All text in this section, +starting at the final @samp{%%} and extending to the end of the input +file, is included verbatim into the generated output file. Naturally, +it is your responsibility to ensure that the code contained in this +section is valid C. + +@node Controls for GNU indent, , Functions, Input Format +@subsection Where to place directives for GNU @code{indent}. + +If you want to invoke GNU @code{indent} on a @code{gperf} input file, +you will see that GNU @code{indent} doesn't understand the @samp{%%}, +@samp{%@{} and @samp{%@}} directives that control @code{gperf}'s +interpretation of the input file. Therefore you have to insert some +directives for GNU @code{indent}. More precisely, assuming the most +general input file structure + +@example +@group +declarations part 1 +%@{ +verbatim code +%@} +declarations part 2 +%% +keywords +%% +functions +@end group +@end example + +@noindent +you would insert @samp{*INDENT-OFF*} and @samp{*INDENT-ON*} comments +as follows: + +@example +@group +/* *INDENT-OFF* */ +declarations part 1 +%@{ +/* *INDENT-ON* */ +verbatim code +/* *INDENT-OFF* */ +%@} +declarations part 2 +%% +keywords +%% +/* *INDENT-ON* */ +functions +@end group +@end example + +@node Output Format, Binary Strings, Input Format, Description +@section Output Format for Generated C Code with @code{gperf} +@cindex hash table + +Several options control how the generated C code appears on the standard +output. Two C function are generated. They are called @code{hash} and +@code{in_word_set}, although you may modify their names with a command-line +option. Both functions require two arguments, a string, @code{char *} +@var{str}, and a length parameter, @code{int} @var{len}. Their default +function prototypes are as follows: + +@deftypefun {unsigned int} hash (const char * @var{str}, unsigned int @var{len}) +By default, the generated @code{hash} function returns an integer value +created by adding @var{len} to several user-specified @var{str} byte +positions indexed into an @dfn{associated values} table stored in a +local static array. The associated values table is constructed +internally by @code{gperf} and later output as a static local C array +called @samp{hash_table}. The relevant selected positions (i.e. indices +into @var{str}) are specified via the @samp{-k} option when running +@code{gperf}, as detailed in the @emph{Options} section below (@pxref{Options}). +@end deftypefun + +@deftypefun {} in_word_set (const char * @var{str}, unsigned int @var{len}) +If @var{str} is in the keyword set, returns a pointer to that +keyword. More exactly, if the option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) was given, it returns +a pointer to the matching keyword's structure. Otherwise it returns +@code{NULL}. +@end deftypefun + +If the option @samp{-c} (or, equivalently, the @samp{%compare-strncmp} +declaration) is not used, @var{str} must be a NUL terminated +string of exactly length @var{len}. If @samp{-c} (or, equivalently, the +@samp{%compare-strncmp} declaration) is used, @var{str} must +simply be an array of @var{len} bytes and does not need to be NUL +terminated. + +The code generated for these two functions is affected by the following +options: + +@table @samp +@item -t +@itemx --struct-type +Make use of the user-defined @code{struct}. + +@item -S @var{total-switch-statements} +@itemx --switch=@var{total-switch-statements} +@cindex @code{switch} +Generate 1 or more C @code{switch} statement rather than use a large, +(and potentially sparse) static array. Although the exact time and +space savings of this approach vary according to your C compiler's +degree of optimization, this method often results in smaller and faster +code. +@end table + +If the @samp{-t} and @samp{-S} options (or, equivalently, the +@samp{%struct-type} and @samp{%switch} declarations) are omitted, the default +action +is to generate a @code{char *} array containing the keywords, together with +additional empty strings used for padding the array. By experimenting +with the various input and output options, and timing the resulting C +code, you can determine the best option choices for different keyword +set characteristics. + +@node Binary Strings, , Output Format, Description +@section Use of NUL bytes +@cindex NUL + +By default, the code generated by @code{gperf} operates on zero +terminated strings, the usual representation of strings in C. This means +that the keywords in the input file must not contain NUL bytes, +and the @var{str} argument passed to @code{hash} or @code{in_word_set} +must be NUL terminated and have exactly length @var{len}. + +If option @samp{-c} (or, equivalently, the @samp{%compare-strncmp} +declaration) is used, then the @var{str} argument does not need +to be NUL terminated. The code generated by @code{gperf} will only +access the first @var{len}, not @var{len+1}, bytes starting at @var{str}. +However, the keywords in the input file still must not contain NUL +bytes. + +If option @samp{-l} (or, equivalently, the @samp{%compare-lengths} +declaration) is used, then the hash table performs binary +comparison. The keywords in the input file may contain NUL bytes, +written in string syntax as @code{\000} or @code{\x00}, and the code +generated by @code{gperf} will treat NUL like any other byte. +Also, in this case the @samp{-c} option (or, equivalently, the +@samp{%compare-strncmp} declaration) is ignored. + +@node Options, Bugs, Description, Top +@chapter Invoking @code{gperf} + +There are @emph{many} options to @code{gperf}. They were added to make +the program more convenient for use with real applications. ``On-line'' +help is readily available via the @samp{--help} option. Here is the +complete list of options. + +@menu +* Output File:: Specifying the Location of the Output File +* Input Details:: Options that affect Interpretation of the Input File +* Output Language:: Specifying the Language for the Output Code +* Output Details:: Fine tuning Details in the Output Code +* Algorithmic Details:: Changing the Algorithms employed by @code{gperf} +* Verbosity:: Informative Output +@end menu + +@node Output File, Input Details, Options, Options +@section Specifying the Location of the Output File + +@table @samp +@item --output-file=@var{file} +Allows you to specify the name of the file to which the output is written to. +@end table + +The results are written to standard output if no output file is specified +or if it is @samp{-}. + +@node Input Details, Output Language, Output File, Options +@section Options that affect Interpretation of the Input File + +These options are also available as declarations in the input file +(@pxref{Gperf Declarations}). + +@table @samp +@item -e @var{keyword-delimiter-list} +@itemx --delimiters=@var{keyword-delimiter-list} +@cindex Delimiters +Allows you to provide a string containing delimiters used to +separate keywords from their attributes. The default is ",". This +option is essential if you want to use keywords that have embedded +commas or newlines. One useful trick is to use -e'TAB', where TAB is +the literal tab character. + +@item -t +@itemx --struct-type +Allows you to include a @code{struct} type declaration for generated +code. Any text before a pair of consecutive @samp{%%} is considered +part of the type declaration. Keywords and additional fields may follow +this, one group of fields per line. A set of examples for generating +perfect hash tables and functions for Ada, C, C++, Pascal, Modula 2, +Modula 3 and JavaScript reserved words are distributed with this release. + +@item --ignore-case +Consider upper and lower case ASCII characters as equivalent. The string +comparison will use a case insignificant character comparison. Note that +locale dependent case mappings are ignored. This option is therefore not +suitable if a properly internationalized or locale aware case mapping +should be used. (For example, in a Turkish locale, the upper case equivalent +of the lowercase ASCII letter @samp{i} is the non-ASCII character +@samp{capital i with dot above}.) For this case, it is better to apply +an uppercase or lowercase conversion on the string before passing it to +the @code{gperf} generated function. +@end table + +@node Output Language, Output Details, Input Details, Options +@section Options to specify the Language for the Output Code + +These options are also available as declarations in the input file +(@pxref{Gperf Declarations}). + +@table @samp +@item -L @var{generated-language-name} +@itemx --language=@var{generated-language-name} +Instructs @code{gperf} to generate code in the language specified by the +option's argument. Languages handled are currently: + +@table @samp +@item KR-C +Old-style K&R C. This language is understood by old-style C compilers and +ANSI C compilers, but ANSI C compilers may flag warnings (or even errors) +because of lacking @samp{const}. + +@item C +Common C. This language is understood by ANSI C compilers, and also by +old-style C compilers, provided that you @code{#define const} to empty +for compilers which don't know about this keyword. + +@item ANSI-C +ANSI C. This language is understood by ANSI C compilers and C++ compilers. + +@item C++ +C++. This language is understood by C++ compilers. +@end table + +The default is C. + +@item -a +This option is supported for compatibility with previous releases of +@code{gperf}. It does not do anything. + +@item -g +This option is supported for compatibility with previous releases of +@code{gperf}. It does not do anything. +@end table + +@node Output Details, Algorithmic Details, Output Language, Options +@section Options for fine tuning Details in the Output Code + +Most of these options are also available as declarations in the input file +(@pxref{Gperf Declarations}). + +@table @samp +@item -K @var{slot-name} +@itemx --slot-name=@var{slot-name} +@cindex Slot name +This option is only useful when option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) has been given. +By default, the program assumes the structure component identifier for +the keyword is @samp{name}. This option allows an arbitrary choice of +identifier for this component, although it still must occur as the first +field in your supplied @code{struct}. + +@item -F @var{initializers} +@itemx --initializer-suffix=@var{initializers} +@cindex Initializers +This option is only useful when option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) has been given. +It permits to specify initializers for the structure members following +@var{slot-name} in empty hash table entries. The list of initializers +should start with a comma. By default, the emitted code will +zero-initialize structure members following @var{slot-name}. + +@item -H @var{hash-function-name} +@itemx --hash-function-name=@var{hash-function-name} +Allows you to specify the name for the generated hash function. Default +name is @samp{hash}. This option permits the use of two hash tables in +the same file. + +@item -N @var{lookup-function-name} +@itemx --lookup-function-name=@var{lookup-function-name} +Allows you to specify the name for the generated lookup function. +Default name is @samp{in_word_set}. This option permits multiple +generated hash functions to be used in the same application. + +@item -Z @var{class-name} +@itemx --class-name=@var{class-name} +@cindex Class name +This option is only useful when option @samp{-L C++} (or, equivalently, +the @samp{%language=C++} declaration) has been given. It +allows you to specify the name of generated C++ class. Default name is +@code{Perfect_Hash}. + +@item -7 +@itemx --seven-bit +This option specifies that all strings that will be passed as arguments +to the generated hash function and the generated lookup function will +solely consist of 7-bit ASCII characters (bytes in the range 0..127). +(Note that the ANSI C functions @code{isalnum} and @code{isgraph} do +@emph{not} guarantee that a byte is in this range. Only an explicit +test like @samp{c >= 'A' && c <= 'Z'} guarantees this.) This was the +default in versions of @code{gperf} earlier than 2.7; now the default is +to support 8-bit and multibyte characters. + +@item -l +@itemx --compare-lengths +Compare keyword lengths before trying a string comparison. This option +is mandatory for binary comparisons (@pxref{Binary Strings}). It also might +cut down on the number of string comparisons made during the lookup, since +keywords with different lengths are never compared via @code{strcmp}. +However, using @samp{-l} might greatly increase the size of the +generated C code if the lookup table range is large (which implies that +the switch option @samp{-S} or @samp{%switch} is not enabled), since the length +table contains as many elements as there are entries in the lookup table. + +@item -c +@itemx --compare-strncmp +Generates C code that uses the @code{strncmp} function to perform +string comparisons. The default action is to use @code{strcmp}. + +@item -C +@itemx --readonly-tables +Makes the contents of all generated lookup tables constant, i.e., +``readonly''. Many compilers can generate more efficient code for this +by putting the tables in readonly memory. + +@item -E +@itemx --enum +Define constant values using an enum local to the lookup function rather +than with #defines. This also means that different lookup functions can +reside in the same file. Thanks to James Clark @code{}. + +@item -I +@itemx --includes +Include the necessary system include file, @code{}, at the +beginning of the code. By default, this is not done; the user must +include this header file himself to allow compilation of the code. + +@item -G +@itemx --global-table +Generate the static table of keywords as a static global variable, +rather than hiding it inside of the lookup function (which is the +default behavior). + +@item -P +@itemx --pic +Optimize the generated table for inclusion in shared libraries. This +reduces the startup time of programs using a shared library containing +the generated code. If the option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) is also given, the first field of the +user-defined struct must be of type @samp{int}, not @samp{char *}, because +it will contain offsets into the string pool instead of actual strings. +To convert such an offset to a string, you can use the expression +@samp{stringpool + @var{o}}, where @var{o} is the offset. The string pool +name can be changed through the option @samp{--string-pool-name}. + +@item -Q @var{string-pool-name} +@itemx --string-pool-name=@var{string-pool-name} +Allows you to specify the name of the generated string pool created by +option @samp{-P}. The default name is @samp{stringpool}. This option +permits the use of two hash tables in the same file, with @samp{-P} and +even when the option @samp{-G} (or, equivalently, the @samp{%global-table} +declaration) is given. + +@item --null-strings +Use NULL strings instead of empty strings for empty keyword table entries. +This reduces the startup time of programs using a shared library containing +the generated code (but not as much as option @samp{-P}), at the expense +of one more test-and-branch instruction at run time. + +@item -W @var{hash-table-array-name} +@itemx --word-array-name=@var{hash-table-array-name} +@cindex Array name +Allows you to specify the name for the generated array containing the +hash table. Default name is @samp{wordlist}. This option permits the +use of two hash tables in the same file, even when the option @samp{-G} +(or, equivalently, the @samp{%global-table} declaration) is given. + +@item -S @var{total-switch-statements} +@itemx --switch=@var{total-switch-statements} +@cindex @code{switch} +Causes the generated C code to use a @code{switch} statement scheme, +rather than an array lookup table. This can lead to a reduction in both +time and space requirements for some input files. The argument to this +option determines how many @code{switch} statements are generated. A +value of 1 generates 1 @code{switch} containing all the elements, a +value of 2 generates 2 tables with 1/2 the elements in each +@code{switch}, etc. This is useful since many C compilers cannot +correctly generate code for large @code{switch} statements. This option +was inspired in part by Keith Bostic's original C program. + +@item -T +@itemx --omit-struct-type +Prevents the transfer of the type declaration to the output file. Use +this option if the type is already defined elsewhere. + +@item -p +This option is supported for compatibility with previous releases of +@code{gperf}. It does not do anything. +@end table + +@node Algorithmic Details, Verbosity, Output Details, Options +@section Options for changing the Algorithms employed by @code{gperf} + +@table @samp +@item -k @var{selected-byte-positions} +@itemx --key-positions=@var{selected-byte-positions} +Allows selection of the byte positions used in the keywords' +hash function. The allowable choices range between 1-255, inclusive. +The positions are separated by commas, e.g., @samp{-k 9,4,13,14}; +ranges may be used, e.g., @samp{-k 2-7}; and positions may occur +in any order. Furthermore, the wildcard '*' causes the generated +hash function to consider @strong{all} byte positions in each keyword, +whereas '$' instructs the hash function to use the ``final byte'' +of a keyword (this is the only way to use a byte position greater than +255, incidentally). + +For instance, the option @samp{-k 1,2,4,6-10,'$'} generates a hash +function that considers positions 1,2,4,6,7,8,9,10, plus the last +byte in each keyword (which may be at a different position for each +keyword, obviously). Keywords +with length less than the indicated byte positions work properly, since +selected byte positions exceeding the keyword length are simply not +referenced in the hash function. + +This option is not normally needed since version 2.8 of @code{gperf}; +the default byte positions are computed depending on the keyword set, +through a search that minimizes the number of byte positions. + +@item -D +@itemx --duplicates +@cindex Duplicates +Handle keywords whose selected byte sets hash to duplicate values. +Duplicate hash values can occur if a set of keywords has the same names, but +possesses different attributes, or if the selected byte positions are not well +chosen. With the -D option @code{gperf} treats all these keywords as +part of an equivalence class and generates a perfect hash function with +multiple comparisons for duplicate keywords. It is up to you to completely +disambiguate the keywords by modifying the generated C code. However, +@code{gperf} helps you out by organizing the output. + +Using this option usually means that the generated hash function is no +longer perfect. On the other hand, it permits @code{gperf} to work on +keyword sets that it otherwise could not handle. + +@item -m @var{iterations} +@itemx --multiple-iterations=@var{iterations} +Perform multiple choices of the @samp{-i} and @samp{-j} values, and +choose the best results. This increases the running time by a factor of +@var{iterations} but does a good job minimizing the generated table size. + +@item -i @var{initial-value} +@itemx --initial-asso=@var{initial-value} +Provides an initial @var{value} for the associate values array. Default +is 0. Increasing the initial value helps inflate the final table size, +possibly leading to more time efficient keyword lookups. Note that this +option is not particularly useful when @samp{-S} (or, equivalently, +@samp{%switch}) is used. Also, +@samp{-i} is overridden when the @samp{-r} option is used. + +@item -j @var{jump-value} +@itemx --jump=@var{jump-value} +@cindex Jump value +Affects the ``jump value'', i.e., how far to advance the associated +byte value upon collisions. @var{Jump-value} is rounded up to an +odd number, the default is 5. If the @var{jump-value} is 0 @code{gperf} +jumps by random amounts. + +@item -n +@itemx --no-strlen +Instructs the generator not to include the length of a keyword when +computing its hash value. This may save a few assembly instructions in +the generated lookup table. + +@item -r +@itemx --random +Utilizes randomness to initialize the associated values table. This +frequently generates solutions faster than using deterministic +initialization (which starts all associated values at 0). Furthermore, +using the randomization option generally increases the size of the +table. + +@item -s @var{size-multiple} +@itemx --size-multiple=@var{size-multiple} +Affects the size of the generated hash table. The numeric argument for +this option indicates ``how many times larger or smaller'' the maximum +associated value range should be, in relationship to the number of keywords. +It can be written as an integer, a floating-point number or a fraction. +For example, a value of 3 means ``allow the maximum associated value to be +about 3 times larger than the number of input keywords''. +Conversely, a value of 1/3 means ``allow the maximum associated value to +be about 3 times smaller than the number of input keywords''. Values +smaller than 1 are useful for limiting the overall size of the generated hash +table, though the option @samp{-m} is better at this purpose. + +If `generate switch' option @samp{-S} (or, equivalently, @samp{%switch}) is +@emph{not} enabled, the maximum +associated value influences the static array table size, and a larger +table should decrease the time required for an unsuccessful search, at +the expense of extra table space. + +The default value is 1, thus the default maximum associated value about +the same size as the number of keywords (for efficiency, the maximum +associated value is always rounded up to a power of 2). The actual +table size may vary somewhat, since this technique is essentially a +heuristic. +@end table + +@node Verbosity, , Algorithmic Details, Options +@section Informative Output + +@table @samp +@item -h +@itemx --help +Prints a short summary on the meaning of each program option. Aborts +further program execution. + +@item -v +@itemx --version +Prints out the current version number. + +@item -d +@itemx --debug +Enables the debugging option. This produces verbose diagnostics to +``standard error'' when @code{gperf} is executing. It is useful both for +maintaining the program and for determining whether a given set of +options is actually speeding up the search for a solution. Some useful +information is dumped at the end of the program when the @samp{-d} +option is enabled. +@end table + +@node Bugs, Projects, Options, Top +@chapter Known Bugs and Limitations with @code{gperf} + +The following are some limitations with the current release of +@code{gperf}: + +@itemize @bullet +@item +The @code{gperf} utility is tuned to execute quickly, and works quickly +for small to medium size data sets (around 1000 keywords). It is +extremely useful for maintaining perfect hash functions for compiler +keyword sets. Several recent enhancements now enable @code{gperf} to +work efficiently on much larger keyword sets (over 15,000 keywords). +When processing large keyword sets it helps greatly to have over 8 megs +of RAM. + +@item +The size of the generate static keyword array can get @emph{extremely} +large if the input keyword file is large or if the keywords are quite +similar. This tends to slow down the compilation of the generated C +code, and @emph{greatly} inflates the object code size. If this +situation occurs, consider using the @samp{-S} option to reduce data +size, potentially increasing keyword recognition time a negligible +amount. Since many C compilers cannot correctly generate code for +large switch statements it is important to qualify the @var{-S} option +with an appropriate numerical argument that controls the number of +switch statements generated. + +@item +The maximum number of selected byte positions has an +arbitrary limit of 255. This restriction should be removed, and if +anyone considers this a problem write me and let me know so I can remove +the constraint. +@end itemize + +@node Projects, Bibliography, Bugs, Top +@chapter Things Still Left to Do + +It should be ``relatively'' easy to replace the current perfect hash +function algorithm with a more exhaustive approach; the perfect hash +module is essential independent from other program modules. Additional +worthwhile improvements include: + +@itemize @bullet +@item +Another useful extension involves modifying the program to generate +``minimal'' perfect hash functions (under certain circumstances, the +current version can be rather extravagant in the generated table size). +This is mostly of theoretical interest, since a sparse table +often produces faster lookups, and use of the @samp{-S} @code{switch} +option can minimize the data size, at the expense of slightly longer +lookups (note that the gcc compiler generally produces good code for +@code{switch} statements, reducing the need for more complex schemes). + +@item +In addition to improving the algorithm, it would also be useful to +generate an Ada package as the code output, in addition to the current +C and C++ routines. +@end itemize + +@page + +@node Bibliography, Concept Index, Projects, Top +@chapter Bibliography + +[1] Chang, C.C.: @i{A Scheme for Constructing Ordered Minimal Perfect +Hashing Functions} Information Sciences 39(1986), 187-195. + +[2] Cichelli, Richard J. @i{Author's Response to ``On Cichelli's Minimal Perfect Hash +Functions Method''} Communications of the ACM, 23, 12(December 1980), 729. + +[3] Cichelli, Richard J. @i{Minimal Perfect Hash Functions Made Simple} +Communications of the ACM, 23, 1(January 1980), 17-19. + +[4] Cook, C. R. and Oldehoeft, R.R. @i{A Letter Oriented Minimal +Perfect Hashing Function} SIGPLAN Notices, 17, 9(September 1982), 18-27. + +[5] Cormack, G. V. and Horspool, R. N. S. and Kaiserwerth, M. +@i{Practical Perfect Hashing} Computer Journal, 28, 1(January 1985), 54-58. + +[6] Jaeschke, G. @i{Reciprocal Hashing: A Method for Generating Minimal +Perfect Hashing Functions} Communications of the ACM, 24, 12(December +1981), 829-833. + +[7] Jaeschke, G. and Osterburg, G. @i{On Cichelli's Minimal Perfect +Hash Functions Method} Communications of the ACM, 23, 12(December 1980), +728-729. + +[8] Sager, Thomas J. @i{A Polynomial Time Generator for Minimal Perfect +Hash Functions} Communications of the ACM, 28, 5(December 1985), 523-532 + +[9] Schmidt, Douglas C. @i{GPERF: A Perfect Hash Function Generator} +Second USENIX C++ Conference Proceedings, April 1990. + +[10] Schmidt, Douglas C. @i{GPERF: A Perfect Hash Function Generator} +C++ Report, SIGS 10 10 (November/December 1998). + +[11] Sebesta, R.W. and Taylor, M.A. @i{Minimal Perfect Hash Functions +for Reserved Word Lists} SIGPLAN Notices, 20, 12(September 1985), 47-53. + +[12] Sprugnoli, R. @i{Perfect Hashing Functions: A Single Probe +Retrieving Method for Static Sets} Communications of the ACM, 20 +11(November 1977), 841-850. + +[13] Stallman, Richard M. @i{Using and Porting GNU CC} Free Software Foundation, +1988. + +[14] Stroustrup, Bjarne @i{The C++ Programming Language.} Addison-Wesley, 1986. + +[15] Tiemann, Michael D. @i{User's Guide to GNU C++} Free Software +Foundation, 1989. + +@node Concept Index, , Bibliography, Top +@unnumbered Concept Index + +@printindex cp + +@contents +@bye diff --git a/contrib/gperf-3.0.1/doc/gpl.texinfo b/contrib/gperf-3.0.1/doc/gpl.texinfo new file mode 100644 index 0000000000..be2dc253c4 --- /dev/null +++ b/contrib/gperf-3.0.1/doc/gpl.texinfo @@ -0,0 +1,398 @@ +@c This GPL is meant to be included from other files. +@c To format a standalone GPL, use license.texi. + +@center Version 2, June 1991 + +@display +Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@unnumberedsec 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. + +@iftex +@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end iftex +@ifinfo +@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end ifinfo + +@enumerate 0 +@item +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. + +@item +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. + +@item +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: + +@enumerate a +@item +You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +@item +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. + +@item +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.) +@end enumerate + +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. + +@item +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: + +@enumerate a +@item +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, + +@item +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, + +@item +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.) +@end enumerate + +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. + +@item +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. + +@item +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. + +@item +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. + +@item +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. + +@item +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. + +@item +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. + +@item +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. + +@iftex +@vskip -@baselineskip +@vskip -@baselineskip +@heading NO WARRANTY +@end iftex +@ifinfo +@center NO WARRANTY +@end ifinfo + +@item +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. + +@item +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 enumerate + +@iftex +@heading END OF TERMS AND CONDITIONS +@end iftex +@ifinfo +@center END OF TERMS AND CONDITIONS +@end ifinfo + +@page +@unnumberedsec 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. + +@smallexample +@var{one line to give the program's name and an idea of what it does.} +Copyright (C) @var{year} @var{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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +@end smallexample + +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: + +@smallexample +Gnomovision version 69, Copyright (C) @var{year} @var{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. +@end smallexample + +The hypothetical commands @samp{show w} and @samp{show c} should show +the appropriate parts of the General Public License. Of course, the +commands you use may be called something other than @samp{show w} and +@samp{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: + +@example +@group +Yoyodyne, Inc., hereby disclaims all copyright +interest in the program `Gnomovision' +(which makes passes at compilers) written +by James Hacker. + +@var{signature of Ty Coon}, 1 April 1989 +Ty Coon, President of Vice +@end group +@end example + +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/contrib/gperf-3.0.1/lib/getline.cc b/contrib/gperf-3.0.1/lib/getline.cc new file mode 100644 index 0000000000..8fc16298bc --- /dev/null +++ b/contrib/gperf-3.0.1/lib/getline.cc @@ -0,0 +1,118 @@ +/* getline.c -- Replacement for GNU C library function getline + +Copyright (C) 1993, 1996, 2001-2002 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 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. */ + +/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ + +/* Specification. */ +#include "getline.h" + +#include +#include +#include +#include + +/* Always add at least this many bytes when extending the buffer. */ +#define MIN_CHUNK 64 + +/* Reads up to (and including) a TERMINATOR from STREAM into *LINEPTR + OFFSET + (and null-terminate it). *LINEPTR is a pointer returned from new [] (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or immediate EOF. + NOTE: There is another getstr() function declared in . */ + +static int +getstr (char **lineptr, size_t *n, FILE *stream, char terminator, size_t offset) +{ + size_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */ + char *read_pos; /* Where we're reading into *LINEPTR. */ + + if (!lineptr || !n || !stream) + return -1; + + if (!*lineptr) + { + *n = MIN_CHUNK; + *lineptr = new char[*n]; + } + + nchars_avail = *n - offset; + read_pos = *lineptr + offset; + + for (;;) + { + register int c = getc (stream); + + /* We always want at least one char left in the buffer, since we + always (unless we get an error while reading the first char) + NUL-terminate the line buffer. */ + + assert (*n - nchars_avail == (size_t) (read_pos - *lineptr)); + if (nchars_avail < 2) + { + if (*n > MIN_CHUNK) + *n *= 2; + else + *n += MIN_CHUNK; + + nchars_avail = *n + *lineptr - read_pos; + char *new_line = new char[*n]; + if (*lineptr) + { + memcpy (new_line, *lineptr, read_pos - *lineptr); + delete[] *lineptr; + } + *lineptr = new_line; + read_pos = *n - nchars_avail + *lineptr; + assert (*n - nchars_avail == (size_t) (read_pos - *lineptr)); + } + + if (c == EOF || ferror (stream)) + { + /* Return partial line, if any. */ + if (read_pos == *lineptr) + return -1; + else + break; + } + + *read_pos++ = c; + nchars_avail--; + + if (c == terminator) + /* Return the line. */ + break; + } + + /* Done - NUL terminate and return the number of chars read. */ + *read_pos = '\0'; + + return read_pos - (*lineptr + offset); +} + +int +get_line (char **lineptr, size_t *n, FILE *stream) +{ + return getstr (lineptr, n, stream, '\n', 0); +} + +int +get_delim (char **lineptr, size_t *n, int delimiter, FILE *stream) +{ + return getstr (lineptr, n, stream, delimiter, 0); +} diff --git a/contrib/gperf-3.0.1/lib/getline.h b/contrib/gperf-3.0.1/lib/getline.h new file mode 100644 index 0000000000..d213f003c5 --- /dev/null +++ b/contrib/gperf-3.0.1/lib/getline.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1995, 2000-2002 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GETLINE_H_ +# define GETLINE_H_ 1 + +# include +# include + +/* Like the glibc functions get_line and get_delim, except that the result + must be freed using delete[], not free(). */ + +/* Reads up to (and including) a newline from STREAM into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from new [] (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or immediate EOF. */ +extern int get_line (char **lineptr, size_t *n, FILE *stream); + +/* Reads up to (and including) a DELIMITER from STREAM into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from new [] (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or immediate EOF. */ +extern int get_delim (char **lineptr, size_t *n, int delimiter, FILE *stream); + +#endif /* not GETLINE_H_ */ diff --git a/contrib/gperf-3.0.1/lib/getopt.c b/contrib/gperf-3.0.1/lib/getopt.c new file mode 100644 index 0000000000..2341d04b22 --- /dev/null +++ b/contrib/gperf-3.0.1/lib/getopt.c @@ -0,0 +1,1042 @@ +/* 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 + 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 . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* 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 +#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 +#include +#endif /* GNU C library. */ + +#ifdef VMS +#include +#if HAVE_STRING_H - 0 +#include +#endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +# include +# 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 = 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 -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 = 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 -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 +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +extern char *getenv (); +extern int strncmp (); + +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; + +#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/contrib/gperf-3.0.1/lib/getopt.c.patch b/contrib/gperf-3.0.1/lib/getopt.c.patch new file mode 100644 index 0000000000..6fedd84a83 --- /dev/null +++ b/contrib/gperf-3.0.1/lib/getopt.c.patch @@ -0,0 +1,25 @@ +getopt.c is a modified version of the getopt.c found in the glibc snapshot +on 1998-04-14. Below the patch that has been applied to this file. The glibc +maintainer has been informed of these patches. + +diff -c3 getopt.c.orig getopt.c +*** getopt.c.orig Sun Mar 8 16:06:55 1998 +--- getopt.c Thu Apr 16 00:09:41 1998 +*************** +*** 201,207 **** + /* Avoid depending on library functions or files + whose names are inconsistent. */ + +! char *getenv (); + + static char * + my_index (str, chr) +--- 201,208 ---- + /* Avoid depending on library functions or files + whose names are inconsistent. */ + +! extern char *getenv (); +! extern int strncmp (); + + static char * + my_index (str, chr) diff --git a/contrib/gperf-3.0.1/lib/getopt.h b/contrib/gperf-3.0.1/lib/getopt.h new file mode 100644 index 0000000000..a9d75f22c8 --- /dev/null +++ b/contrib/gperf-3.0.1/lib/getopt.h @@ -0,0 +1,138 @@ +/* Declarations for getopt. + Copyright (C) 1989-1998, 2000 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 +#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 -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; + +/* 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__) || defined (__cplusplus) + 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__) || defined (__cplusplus) +#ifdef __cplusplus +/* SunOS4 declares getopt with the following prototype: + extern int getopt (int argc, const char *const *argv, const char *shortopts); + We cannot redeclare it when compiling C++ code. */ +#define getopt(x,y,z) getopt_long(x, y, z, (const struct option *) 0, (int *) 0) +#else /* not __cplusplus */ +#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__ */ +#endif /* __cplusplus */ +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/contrib/gperf-3.0.1/lib/getopt.h.patch b/contrib/gperf-3.0.1/lib/getopt.h.patch new file mode 100644 index 0000000000..8094b1a65d --- /dev/null +++ b/contrib/gperf-3.0.1/lib/getopt.h.patch @@ -0,0 +1,70 @@ +getopt.h is a modified version of the getopt.h found in the glibc snapshot +on 1998-04-14. Below the patch that has been applied to this file. The glibc +maintainer has been informed of these patches. + +diff -c3 getopt.h.orig getopt.h +*** getopt.h.orig Sat Jun 21 03:01:53 1997 +--- getopt.h Mon Aug 28 12:36:27 2000 +*************** +*** 1,5 **** + /* Declarations for getopt. +! Copyright (C) 1989,90,91,92,93,94,96,97 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 +--- 1,5 ---- + /* Declarations for getopt. +! Copyright (C) 1989-1998, 2000 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 +*************** +*** 78,84 **** + + struct option + { +! #if defined (__STDC__) && __STDC__ + const char *name; + #else + char *name; +--- 78,84 ---- + + struct option + { +! #if (defined (__STDC__) && __STDC__) || defined (__cplusplus) + const char *name; + #else + char *name; +*************** +*** 96,102 **** + #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 +--- 96,108 ---- + #define required_argument 1 + #define optional_argument 2 + +! #if (defined (__STDC__) && __STDC__) || defined (__cplusplus) +! #ifdef __cplusplus +! /* SunOS4 declares getopt with the following prototype: +! extern int getopt (int argc, const char *const *argv, const char *shortopts); +! We cannot redeclare it when compiling C++ code. */ +! #define getopt(x,y,z) getopt_long(x, y, z, (const struct option *) 0, (int *) 0) +! #else /* not __cplusplus */ + #ifdef __GNU_LIBRARY__ + /* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation +*************** +*** 105,110 **** +--- 111,117 ---- + #else /* not __GNU_LIBRARY__ */ + extern int getopt (); + #endif /* __GNU_LIBRARY__ */ ++ #endif /* __cplusplus */ + 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, diff --git a/contrib/gperf-3.0.1/lib/getopt1.c b/contrib/gperf-3.0.1/lib/getopt1.c new file mode 100644 index 0000000000..3d264f2db4 --- /dev/null +++ b/contrib/gperf-3.0.1/lib/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 +#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 + +/* 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 +#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 +#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 + +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/contrib/gperf-3.0.1/lib/hash.cc b/contrib/gperf-3.0.1/lib/hash.cc new file mode 100644 index 0000000000..1795cee81c --- /dev/null +++ b/contrib/gperf-3.0.1/lib/hash.cc @@ -0,0 +1,27 @@ +/* +Copyright (C) 1990, 2000, 2002 Free Software Foundation + written by Doug Lea +*/ + +#include + +/* + Some useful hash function. + It's not a particularly good hash function (<< 5 would be better than << 4), + but people believe in it because it comes from Dragon book. +*/ + +unsigned int +hashpjw (const unsigned char *x, unsigned int len) // From Dragon book, p436 +{ + unsigned int h = 0; + unsigned int g; + + for (; len > 0; len--) + { + h = (h << 4) + *x++; + if ((g = h & 0xf0000000) != 0) + h = (h ^ (g >> 24)) ^ g; + } + return h; +} diff --git a/contrib/gperf-3.0.1/lib/hash.h b/contrib/gperf-3.0.1/lib/hash.h new file mode 100644 index 0000000000..d202e723ad --- /dev/null +++ b/contrib/gperf-3.0.1/lib/hash.h @@ -0,0 +1,15 @@ +// This may look like C code, but it is really -*- C++ -*- + +/* +Copyright (C) 1988, 1992, 2000, 2002 Free Software Foundation + written by Doug Lea +*/ + +#ifndef _hash_h +#define _hash_h 1 + +/* a hash function for char[] arrays using the + method described in Aho, Sethi, & Ullman, p 436. */ +extern unsigned int hashpjw (const unsigned char *string, unsigned int len); + +#endif diff --git a/contrib/gperf-3.0.1/src/bool-array.cc b/contrib/gperf-3.0.1/src/bool-array.cc new file mode 100644 index 0000000000..330ca1750d --- /dev/null +++ b/contrib/gperf-3.0.1/src/bool-array.cc @@ -0,0 +1,47 @@ +/* Fast lookup table abstraction implemented as an Iteration Number Array + Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "bool-array.h" + +#include +#include +#include "options.h" + +/* Frees this object. */ +Bool_Array::~Bool_Array () +{ + /* Print out debugging diagnostics. */ + if (option[DEBUG]) + fprintf (stderr, "\ndumping boolean array information\n" + "size = %d\niteration number = %d\nend of array dump\n", + _size, _iteration_number); + delete[] const_cast(_storage_array); +} + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "bool-array.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/contrib/gperf-3.0.1/src/bool-array.h b/contrib/gperf-3.0.1/src/bool-array.h new file mode 100644 index 0000000000..e92d61978c --- /dev/null +++ b/contrib/gperf-3.0.1/src/bool-array.h @@ -0,0 +1,79 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Simple lookup table abstraction implemented as an Iteration Number Array. + + Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef bool_array_h +#define bool_array_h 1 + +/* A Bool_Array instance is a bit array of fixed size, optimized for being + filled sparsely and cleared frequently. For example, when processing + tests/chill.gperf, the array will be: + - of size 15391, + - clear will be called 3509 times, + - set_bit will be called 300394 times. + With a conventional bit array implementation, clear would be too slow. + With a tree/hash based bit array implementation, set_bit would be slower. */ + +class Bool_Array +{ +public: + /* Initializes the bit array with room for SIZE bits, numbered from + 0 to SIZE-1. */ + Bool_Array (unsigned int size); + + /* Frees this object. */ + ~Bool_Array (); + + /* Resets all bits to zero. */ + void clear (); + + /* Sets the specified bit to true. + Returns its previous value (false or true). */ + bool set_bit (unsigned int index); + +private: + /* Size of array. */ + unsigned int const _size; + + /* Current iteration number. Always nonzero. Starts out as 1, and is + incremented each time clear() is called. */ + unsigned int _iteration_number; + + /* For each index, we store in storage_array[index] the iteration_number at + the time set_bit(index) was last called. */ + unsigned int * const _storage_array; +}; + +#ifdef __OPTIMIZE__ /* efficiency hack! */ + +#include +#include +#include "options.h" +#define INLINE inline +#include "bool-array.icc" +#undef INLINE + +#endif + +#endif diff --git a/contrib/gperf-3.0.1/src/bool-array.icc b/contrib/gperf-3.0.1/src/bool-array.icc new file mode 100644 index 0000000000..63e6adb49e --- /dev/null +++ b/contrib/gperf-3.0.1/src/bool-array.icc @@ -0,0 +1,78 @@ +/* Inline Functions for bool-array.{h,cc}. + + Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +// This needs: +//#include +//#include +//#include "options.h" + +/* Initializes the bit array with room for SIZE bits, numbered from + 0 to SIZE-1. */ +INLINE +Bool_Array::Bool_Array (unsigned int size) + : _size (size), + _iteration_number (1), + _storage_array (new unsigned int [size]) +{ + memset (_storage_array, 0, size * sizeof (_storage_array[0])); + if (option[DEBUG]) + fprintf (stderr, "\nbool array size = %d, total bytes = %d\n", + _size, + static_cast (_size * sizeof (_storage_array[0]))); +} + +/* Sets the specified bit to true. + Returns its previous value (false or true). */ +INLINE bool +Bool_Array::set_bit (unsigned int index) +{ + if (_storage_array[index] == _iteration_number) + /* The bit was set since the last clear() call. */ + return true; + else + { + /* The last operation on this bit was clear(). Set it now. */ + _storage_array[index] = _iteration_number; + return false; + } +} + +/* Resets all bits to zero. */ +INLINE void +Bool_Array::clear () +{ + /* If we wrap around it's time to zero things out again! However, this only + occurs once about every 2^32 iterations, so it will not happen more + frequently than once per second. */ + + if (++_iteration_number == 0) + { + _iteration_number = 1; + memset (_storage_array, 0, _size * sizeof (_storage_array[0])); + if (option[DEBUG]) + { + fprintf (stderr, "(re-initialized bool_array)\n"); + fflush (stderr); + } + } +} diff --git a/contrib/gperf-3.0.1/src/config.h.in b/contrib/gperf-3.0.1/src/config.h.in new file mode 100644 index 0000000000..520d7d64fc --- /dev/null +++ b/contrib/gperf-3.0.1/src/config.h.in @@ -0,0 +1,20 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if the C++ compiler supports stack-allocated variable-size arrays. + */ +#undef HAVE_DYNAMIC_ARRAY + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION diff --git a/contrib/gperf-3.0.1/src/config.h.msvc b/contrib/gperf-3.0.1/src/config.h.msvc new file mode 100644 index 0000000000..520d7d64fc --- /dev/null +++ b/contrib/gperf-3.0.1/src/config.h.msvc @@ -0,0 +1,20 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if the C++ compiler supports stack-allocated variable-size arrays. + */ +#undef HAVE_DYNAMIC_ARRAY + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION diff --git a/contrib/gperf-3.0.1/src/config.h_vms b/contrib/gperf-3.0.1/src/config.h_vms new file mode 100644 index 0000000000..520d7d64fc --- /dev/null +++ b/contrib/gperf-3.0.1/src/config.h_vms @@ -0,0 +1,20 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if the C++ compiler supports stack-allocated variable-size arrays. + */ +#undef HAVE_DYNAMIC_ARRAY + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION diff --git a/contrib/gperf-3.0.1/src/configure b/contrib/gperf-3.0.1/src/configure new file mode 100644 index 0000000000..317bb2901e --- /dev/null +++ b/contrib/gperf-3.0.1/src/configure @@ -0,0 +1,4190 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.57. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="main.cc" +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP CXX CXXFLAGS ac_ct_CXX CXXCPP INSTALL INSTALL_PROGRAM INSTALL_DATA GPERF_LIBM LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +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' + +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 + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # 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_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$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 ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) 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 | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$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 | -n) + 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_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + 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 "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# 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_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + 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 "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # 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 <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# 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 + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# 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 "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + ac_config_headers="$ac_config_headers config.h" + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 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 conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +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 "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +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 $# != 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 + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +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 "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&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 "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# 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 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +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 "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + # 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 "$as_me:$LINENO: checking for a BSD compatible install" >&5 +echo $ECHO_N "checking for a BSD compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${cl_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + IFS="${IFS= }"; ac_save_ifs="$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. + 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 + if test $ac_prog = installbsd && + grep src/bos $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX installbsd doesn't work without option "-g". + : + else + cl_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + fi + done + ;; + esac + done + IFS="$ac_save_ifs" + # As a last resort, use cp. + test -z "$cl_cv_path_install" && cl_cv_path_install="cp" + +fi + INSTALL="$cl_cv_path_install" +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&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)' +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi + + echo "$as_me:$LINENO: checking for stack-allocated variable-size arrays" >&5 +echo $ECHO_N "checking for stack-allocated variable-size arrays... $ECHO_C" >&6 + +if test "${gp_cv_cxx_dynamic_array+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int func (int n) { int dynamic_array[n]; } +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gp_cv_cxx_dynamic_array=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gp_cv_cxx_dynamic_array=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi + +echo "$as_me:$LINENO: result: $gp_cv_cxx_dynamic_array" >&5 +echo "${ECHO_T}$gp_cv_cxx_dynamic_array" >&6 +if test $gp_cv_cxx_dynamic_array = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DYNAMIC_ARRAY 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for rand in -lm" >&5 +echo $ECHO_N "checking for rand in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_rand+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char rand (); +int +main () +{ +rand (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_rand=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_rand=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_rand" >&5 +echo "${ECHO_T}$ac_cv_lib_m_rand" >&6 +if test $ac_cv_lib_m_rand = yes; then + GPERF_LIBM="-lm" +else + GPERF_LIBM="" +fi + + + ac_config_files="$ac_config_files Makefile" +cat >confcache <<\_ACEOF +# 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, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# 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 \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@INSTALL@,$INSTALL,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@GPERF_LIBM@,$GPERF_LIBM,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # 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_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # 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" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# 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=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# 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.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# 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.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/contrib/gperf-3.0.1/src/configure.in b/contrib/gperf-3.0.1/src/configure.in new file mode 100644 index 0000000000..ef7883f8b6 --- /dev/null +++ b/contrib/gperf-3.0.1/src/configure.in @@ -0,0 +1,67 @@ +dnl autoconf configuration for gperf/src + +dnl Copyright (C) 1998, 2000, 2002-2003 Free Software Foundation, Inc. +dnl Written by Douglas C. Schmidt +dnl and Bruno Haible . +dnl +dnl This file is part of GNU GPERF. +dnl +dnl GNU GPERF is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU GPERF is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; see the file COPYING. +dnl If not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +AC_INIT(main.cc) +AC_CONFIG_HEADER(config.h) +AC_PROG_MAKE_SET +dnl +dnl checks for programs +dnl +AC_PROG_CC + dnl sets variable CC +AC_PROG_CPP + dnl sets variable CPP +AC_PROG_CXX + dnl sets variable CXX +AC_PROG_CXXCPP + dnl sets variable CXXCPP +CL_PROG_INSTALL + dnl sets variables INSTALL, INSTALL_DATA, INSTALL_PROGRAM +dnl +dnl checks for compiler characteristics +dnl +AC_MSG_CHECKING([for stack-allocated variable-size arrays]) +AC_CACHE_VAL(gp_cv_cxx_dynamic_array, [ +AC_LANG_SAVE() +AC_LANG_CPLUSPLUS() +AC_TRY_COMPILE([int func (int n) { int dynamic_array[n]; }], [], +gp_cv_cxx_dynamic_array=yes, gp_cv_cxx_dynamic_array=no) +AC_LANG_RESTORE() +]) +AC_MSG_RESULT($gp_cv_cxx_dynamic_array) +if test $gp_cv_cxx_dynamic_array = yes; then + AC_DEFINE(HAVE_DYNAMIC_ARRAY, 1, + [Define if the C++ compiler supports stack-allocated variable-size arrays.]) +fi +dnl +dnl checks for functions and declarations +dnl +dnl +dnl checks for libraries +dnl +AC_CHECK_LIB(m, rand, GPERF_LIBM="-lm", GPERF_LIBM="") +AC_SUBST(GPERF_LIBM) +dnl +dnl That's it. +dnl +AC_OUTPUT(Makefile) diff --git a/contrib/gperf-3.0.1/src/hash-table.cc b/contrib/gperf-3.0.1/src/hash-table.cc new file mode 100644 index 0000000000..615afd681d --- /dev/null +++ b/contrib/gperf-3.0.1/src/hash-table.cc @@ -0,0 +1,167 @@ +/* Hash table for checking keyword links. Implemented using double hashing. + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "hash-table.h" + +#include +#include /* declares memset(), strcmp() */ +#include +#include "options.h" + +/* We use a hash table with double hashing. This is the simplest kind of + hash table, given that we always only insert and never remove entries + from the hash table. */ + +/* To make double hashing efficient, there need to be enough spare entries. */ +static const int size_factor = 10; + +/* We make the size of the hash table a power of 2. This allows for two + optimizations: It eliminates the modulo instruction, and allows for an + easy secondary hashing function. */ + +/* Constructor. */ +Hash_Table::Hash_Table (unsigned int size, bool ignore_length) + : _ignore_length (ignore_length), + _collisions (0) +{ + /* There need to be enough spare entries. */ + size = size * size_factor; + + /* Find smallest power of 2 that is >= size. */ + unsigned int shift = 0; + if ((size >> 16) > 0) + { + size = size >> 16; + shift += 16; + } + if ((size >> 8) > 0) + { + size = size >> 8; + shift += 8; + } + if ((size >> 4) > 0) + { + size = size >> 4; + shift += 4; + } + if ((size >> 2) > 0) + { + size = size >> 2; + shift += 2; + } + if ((size >> 1) > 0) + { + size = size >> 1; + shift += 1; + } + _log_size = shift; + _size = 1 << shift; + + /* Allocate table. */ + _table = new KeywordExt*[_size]; + memset (_table, 0, _size * sizeof (*_table)); +} + +/* Destructor. */ +Hash_Table::~Hash_Table () +{ + delete[] _table; +} + +/* Print the table's contents. */ +void +Hash_Table::dump () const +{ + int field_width; + + field_width = 0; + { + for (int i = _size - 1; i >= 0; i--) + if (_table[i]) + if (field_width < _table[i]->_selchars_length) + field_width = _table[i]->_selchars_length; + } + + fprintf (stderr, + "\ndumping the hash table\n" + "total available table slots = %d, total bytes = %d, total collisions = %d\n" + "location, %*s, keyword\n", + _size, _size * static_cast(sizeof (*_table)), + _collisions, field_width, "keysig"); + + for (int i = _size - 1; i >= 0; i--) + if (_table[i]) + { + fprintf (stderr, "%8d, ", i); + if (field_width > _table[i]->_selchars_length) + fprintf (stderr, "%*s", field_width - _table[i]->_selchars_length, ""); + for (int j = 0; j < _table[i]->_selchars_length; j++) + putc (_table[i]->_selchars[j], stderr); + fprintf (stderr, ", %.*s\n", + _table[i]->_allchars_length, _table[i]->_allchars); + } + + fprintf (stderr, "\nend dumping hash table\n\n"); +} + +/* Compares two items. */ +inline bool +Hash_Table::equal (KeywordExt *item1, KeywordExt *item2) const +{ + return item1->_selchars_length == item2->_selchars_length + && memcmp (item1->_selchars, item2->_selchars, + item2->_selchars_length * sizeof (unsigned int)) + == 0 + && (_ignore_length + || item1->_allchars_length == item2->_allchars_length); +} + +/* Attempts to insert ITEM in the table. If there is already an equal + entry in it, returns it. Otherwise inserts ITEM and returns NULL. */ +KeywordExt * +Hash_Table::insert (KeywordExt *item) +{ + unsigned hash_val = + hashpjw (reinterpret_cast(item->_selchars), + item->_selchars_length * sizeof (unsigned int)); + unsigned int probe = hash_val & (_size - 1); + unsigned int increment = + (((hash_val >> _log_size) + ^ (_ignore_length ? 0 : item->_allchars_length)) + << 1) + 1; + /* Note that because _size is a power of 2 and increment is odd, + we have gcd(increment,_size) = 1, which guarantees that we'll find + an empty entry during the loop. */ + + while (_table[probe] != NULL) + { + if (equal (_table[probe], item)) + return _table[probe]; + + _collisions++; + probe = (probe + increment) & (_size - 1); + } + + _table[probe] = item; + return NULL; +} diff --git a/contrib/gperf-3.0.1/src/hash-table.h b/contrib/gperf-3.0.1/src/hash-table.h new file mode 100644 index 0000000000..8b7f6a2e5d --- /dev/null +++ b/contrib/gperf-3.0.1/src/hash-table.h @@ -0,0 +1,66 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Hash table used to check for duplicate keyword entries. + + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef hash_table_h +#define hash_table_h 1 + +#include "keyword.h" + +/* Hash table of KeywordExt* entries. + Two entries are considered equal if their _selchars are the same and + - if !ignore_length - if their _allchars_length are the same. */ + +class Hash_Table +{ +public: + /* Constructor. + size is the maximum number of entries. + ignore_length determines a detail in the comparison function. */ + Hash_Table (unsigned int size, bool ignore_length); + /* Destructor. */ + ~Hash_Table (); + /* Attempts to insert ITEM in the table. If there is already an equal + entry in it, returns it. Otherwise inserts ITEM and returns NULL. */ + KeywordExt * insert (KeywordExt *item); + /* Print the table's contents. */ + void dump () const; + +private: + /* Vector of entries. */ + KeywordExt ** _table; + /* Size of the vector. */ + unsigned int _size; + /* log2(_size). */ + unsigned int _log_size; + /* A detail of the comparison function. */ + bool const _ignore_length; + /* Statistics: Number of collisions so far. */ + unsigned int _collisions; + + /* Compares two items. */ + bool equal (KeywordExt *item1, KeywordExt *item2) const; +}; + +#endif diff --git a/contrib/gperf-3.0.1/src/input.cc b/contrib/gperf-3.0.1/src/input.cc new file mode 100644 index 0000000000..1b2c4595a9 --- /dev/null +++ b/contrib/gperf-3.0.1/src/input.cc @@ -0,0 +1,1000 @@ +/* Input routines. + Copyright (C) 1989-1998, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "input.h" + +#include +#include /* declares exit() */ +#include /* declares strncpy(), strchr() */ +#include /* defines UCHAR_MAX etc. */ +#include "options.h" +#include "getline.h" + +Input::Input (FILE *stream, Keyword_Factory *keyword_factory) + : _stream (stream), _factory (keyword_factory) +{ +} + +/* Returns a pretty representation of the input file name, for error and + warning messages. */ +static const char * +pretty_input_file_name () +{ + if (option.get_input_file_name ()) + return option.get_input_file_name (); + else + return "(standard input)"; +} + +/* Returns true if the given line contains a "%DECL" declaration. */ +static bool +is_declaration (const char *line, const char *line_end, unsigned int lineno, + const char *decl) +{ + /* Skip '%'. */ + line++; + + /* Skip DECL. */ + for (const char *d = decl; *d; d++) + { + if (!(line < line_end)) + return false; + if (!(*line == *d || (*d == '-' && *line == '_'))) + return false; + line++; + } + if (line < line_end + && ((*line >= 'A' && *line <= 'Z') + || (*line >= 'a' && *line <= 'z') + || *line == '-' || *line == '_')) + return false; + + /* OK, found DECL. */ + + /* Skip whitespace. */ + while (line < line_end && (*line == ' ' || *line == '\t')) + line++; + + /* Expect end of line. */ + if (line < line_end && *line != '\n') + { + fprintf (stderr, "%s:%u: junk after declaration\n", + pretty_input_file_name (), lineno); + exit (1); + } + + return true; +} + +/* Tests if the given line contains a "%DECL=ARG" declaration. + If yes, it sets *ARGP to the argument, and returns true. + Otherwise, it returns false. */ +static bool +is_declaration_with_arg (const char *line, const char *line_end, + unsigned int lineno, + const char *decl, char **argp) +{ + /* Skip '%'. */ + line++; + + /* Skip DECL. */ + for (const char *d = decl; *d; d++) + { + if (!(line < line_end)) + return false; + if (!(*line == *d || (*d == '-' && *line == '_'))) + return false; + line++; + } + if (line < line_end + && ((*line >= 'A' && *line <= 'Z') + || (*line >= 'a' && *line <= 'z') + || *line == '-' || *line == '_')) + return false; + + /* OK, found DECL. */ + + /* Skip '='. */ + if (!(line < line_end && *line == '=')) + { + fprintf (stderr, "%s:%u: missing argument in %%%s=ARG declaration.\n", + pretty_input_file_name (), lineno, decl); + exit (1); + } + line++; + + /* The next word is the argument. */ + char *arg = new char[line_end - line + 1]; + char *p = arg; + while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n')) + *p++ = *line++; + *p = '\0'; + + /* Skip whitespace. */ + while (line < line_end && (*line == ' ' || *line == '\t')) + line++; + + /* Expect end of line. */ + if (line < line_end && *line != '\n') + { + fprintf (stderr, "%s:%u: junk after declaration\n", + pretty_input_file_name (), lineno); + exit (1); + } + + *argp = arg; + return true; +} + +/* Tests if the given line contains a "%define DECL ARG" declaration. + If yes, it sets *ARGP to the argument, and returns true. + Otherwise, it returns false. */ +static bool +is_define_declaration (const char *line, const char *line_end, + unsigned int lineno, + const char *decl, char **argp) +{ + /* Skip '%'. */ + line++; + + /* Skip "define". */ + { + for (const char *d = "define"; *d; d++) + { + if (!(line < line_end)) + return false; + if (!(*line == *d)) + return false; + line++; + } + if (!(line < line_end && (*line == ' ' || *line == '\t'))) + return false; + } + + /* Skip whitespace. */ + while (line < line_end && (*line == ' ' || *line == '\t')) + line++; + + /* Skip DECL. */ + for (const char *d = decl; *d; d++) + { + if (!(line < line_end)) + return false; + if (!(*line == *d || (*d == '-' && *line == '_'))) + return false; + line++; + } + if (line < line_end + && ((*line >= 'A' && *line <= 'Z') + || (*line >= 'a' && *line <= 'z') + || *line == '-' || *line == '_')) + return false; + + /* OK, found DECL. */ + + /* Skip whitespace. */ + if (!(line < line_end && (*line == ' ' || *line == '\t'))) + { + fprintf (stderr, "%s:%u:" + " missing argument in %%define %s ARG declaration.\n", + pretty_input_file_name (), lineno, decl); + exit (1); + } + do + line++; + while (line < line_end && (*line == ' ' || *line == '\t')); + + /* The next word is the argument. */ + char *arg = new char[line_end - line + 1]; + char *p = arg; + while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n')) + *p++ = *line++; + *p = '\0'; + + /* Skip whitespace. */ + while (line < line_end && (*line == ' ' || *line == '\t')) + line++; + + /* Expect end of line. */ + if (line < line_end && *line != '\n') + { + fprintf (stderr, "%s:%u: junk after declaration\n", + pretty_input_file_name (), lineno); + exit (1); + } + + *argp = arg; + return true; +} + +/* Reads the entire input file. */ +void +Input::read_input () +{ + /* The input file has the following structure: + DECLARATIONS + %% + KEYWORDS + %% + ADDITIONAL_CODE + Since the DECLARATIONS and the ADDITIONAL_CODE sections are optional, + we have to read the entire file in the case there is only one %% + separator line, in order to determine whether the structure is + DECLARATIONS + %% + KEYWORDS + or + KEYWORDS + %% + ADDITIONAL_CODE + When the option -t is given or when the first section contains + declaration lines starting with %, we go for the first interpretation, + otherwise for the second interpretation. */ + + char *input = NULL; + size_t input_size = 0; + int input_length = get_delim (&input, &input_size, EOF, _stream); + if (input_length < 0) + { + if (ferror (_stream)) + fprintf (stderr, "%s: error while reading input file\n", + pretty_input_file_name ()); + else + fprintf (stderr, "%s: The input file is empty!\n", + pretty_input_file_name ()); + exit (1); + } + + /* We use input_end as a limit, in order to cope with NUL bytes in the + input. But note that one trailing NUL byte has been added after + input_end, for convenience. */ + char *input_end = input + input_length; + + const char *declarations; + const char *declarations_end; + const char *keywords; + const char *keywords_end; + unsigned int keywords_lineno; + + /* Break up the input into the three sections. */ + { + const char *separator[2] = { NULL, NULL }; + unsigned int separator_lineno[2] = { 0, 0 }; + int separators = 0; + { + unsigned int lineno = 1; + for (const char *p = input; p < input_end; ) + { + if (p[0] == '%' && p[1] == '%') + { + separator[separators] = p; + separator_lineno[separators] = lineno; + if (++separators == 2) + break; + } + lineno++; + p = (const char *) memchr (p, '\n', input_end - p); + if (p != NULL) + p++; + else + p = input_end; + } + } + + bool has_declarations; + if (separators == 1) + { + if (option[TYPE]) + has_declarations = true; + else + { + has_declarations = false; + for (const char *p = input; p < separator[0]; ) + { + if (p[0] == '%') + { + has_declarations = true; + break; + } + p = (const char *) memchr (p, '\n', separator[0] - p); + if (p != NULL) + p++; + else + p = separator[0]; + } + } + } + else + has_declarations = (separators > 0); + + if (has_declarations) + { + declarations = input; + declarations_end = separator[0]; + /* Give a warning if the separator line is nonempty. */ + bool nonempty_line = false; + const char *p; + for (p = declarations_end + 2; p < input_end; ) + { + if (*p == '\n') + { + p++; + break; + } + if (!(*p == ' ' || *p == '\t')) + nonempty_line = true; + p++; + } + if (nonempty_line) + fprintf (stderr, "%s:%u: warning: junk after %%%% is ignored\n", + pretty_input_file_name (), separator_lineno[0]); + keywords = p; + keywords_lineno = separator_lineno[0] + 1; + } + else + { + declarations = NULL; + declarations_end = NULL; + keywords = input; + keywords_lineno = 1; + } + + if (separators > (has_declarations ? 1 : 0)) + { + keywords_end = separator[separators-1]; + _verbatim_code = separator[separators-1] + 2; + _verbatim_code_end = input_end; + _verbatim_code_lineno = separator_lineno[separators-1]; + } + else + { + keywords_end = input_end; + _verbatim_code = NULL; + _verbatim_code_end = NULL; + _verbatim_code_lineno = 0; + } + } + + /* Parse the declarations section. */ + + _verbatim_declarations = NULL; + _verbatim_declarations_end = NULL; + _verbatim_declarations_lineno = 0; + _struct_decl = NULL; + _struct_decl_lineno = 0; + _return_type = NULL; + _struct_tag = NULL; + { + unsigned int lineno = 1; + char *struct_decl = NULL; + unsigned int *struct_decl_linenos = NULL; + unsigned int struct_decl_linecount = 0; + for (const char *line = declarations; line < declarations_end; ) + { + const char *line_end; + line_end = (const char *) memchr (line, '\n', declarations_end - line); + if (line_end != NULL) + line_end++; + else + line_end = declarations_end; + + if (*line == '%') + { + if (line[1] == '{') + { + /* Handle %{. */ + if (_verbatim_declarations != NULL) + { + fprintf (stderr, "%s:%u:\n%s:%u:" + " only one %%{...%%} section is allowed\n", + pretty_input_file_name (), + _verbatim_declarations_lineno, + pretty_input_file_name (), lineno); + exit (1); + } + _verbatim_declarations = line + 2; + _verbatim_declarations_lineno = lineno; + } + else if (line[1] == '}') + { + /* Handle %}. */ + if (_verbatim_declarations == NULL) + { + fprintf (stderr, "%s:%u:" + " %%} outside of %%{...%%} section\n", + pretty_input_file_name (), lineno); + exit (1); + } + if (_verbatim_declarations_end != NULL) + { + fprintf (stderr, "%s:%u:" + " %%{...%%} section already closed\n", + pretty_input_file_name (), lineno); + exit (1); + } + _verbatim_declarations_end = line; + /* Give a warning if the rest of the line is nonempty. */ + bool nonempty_line = false; + const char *q; + for (q = line + 2; q < line_end; q++) + { + if (*q == '\n') + { + q++; + break; + } + if (!(*q == ' ' || *q == '\t')) + nonempty_line = true; + } + if (nonempty_line) + fprintf (stderr, "%s:%u:" + " warning: junk after %%} is ignored\n", + pretty_input_file_name (), lineno); + } + else if (_verbatim_declarations != NULL + && _verbatim_declarations_end == NULL) + { + fprintf (stderr, "%s:%u:" + " warning: %% directives are ignored" + " inside the %%{...%%} section\n", + pretty_input_file_name (), lineno); + } + else + { + char *arg; + + if (is_declaration_with_arg (line, line_end, lineno, + "delimiters", &arg)) + option.set_delimiters (arg); + else + + if (is_declaration (line, line_end, lineno, "struct-type")) + option.set (TYPE); + else + + if (is_declaration (line, line_end, lineno, "ignore-case")) + option.set (UPPERLOWER); + else + + if (is_declaration_with_arg (line, line_end, lineno, + "language", &arg)) + option.set_language (arg); + else + + if (is_define_declaration (line, line_end, lineno, + "slot-name", &arg)) + option.set_slot_name (arg); + else + + if (is_define_declaration (line, line_end, lineno, + "initializer-suffix", &arg)) + option.set_initializer_suffix (arg); + else + + if (is_define_declaration (line, line_end, lineno, + "hash-function-name", &arg)) + option.set_hash_name (arg); + else + + if (is_define_declaration (line, line_end, lineno, + "lookup-function-name", &arg)) + option.set_function_name (arg); + else + + if (is_define_declaration (line, line_end, lineno, + "class-name", &arg)) + option.set_class_name (arg); + else + + if (is_declaration (line, line_end, lineno, "7bit")) + option.set (SEVENBIT); + else + + if (is_declaration (line, line_end, lineno, "compare-lengths")) + option.set (LENTABLE); + else + + if (is_declaration (line, line_end, lineno, "compare-strncmp")) + option.set (COMP); + else + + if (is_declaration (line, line_end, lineno, "readonly-tables")) + option.set (CONST); + else + + if (is_declaration (line, line_end, lineno, "enum")) + option.set (ENUM); + else + + if (is_declaration (line, line_end, lineno, "includes")) + option.set (INCLUDE); + else + + if (is_declaration (line, line_end, lineno, "global-table")) + option.set (GLOBAL); + else + + if (is_declaration (line, line_end, lineno, "pic")) + option.set (SHAREDLIB); + else + + if (is_define_declaration (line, line_end, lineno, + "string-pool-name", &arg)) + option.set_stringpool_name (arg); + else + + if (is_declaration (line, line_end, lineno, "null-strings")) + option.set (NULLSTRINGS); + else + + if (is_define_declaration (line, line_end, lineno, + "word-array-name", &arg)) + option.set_wordlist_name (arg); + else + + if (is_declaration_with_arg (line, line_end, lineno, + "switch", &arg)) + { + option.set_total_switches (atoi (arg)); + if (option.get_total_switches () <= 0) + { + fprintf (stderr, "%s:%u: number of switches %s" + " must be a positive number\n", + pretty_input_file_name (), lineno, arg); + exit (1); + } + } + else + + if (is_declaration (line, line_end, lineno, "omit-struct-type")) + option.set (NOTYPE); + else + + { + fprintf (stderr, "%s:%u: unrecognized %% directive\n", + pretty_input_file_name (), lineno); + exit (1); + } + } + } + else if (!(_verbatim_declarations != NULL + && _verbatim_declarations_end == NULL)) + { + /* Append the line to struct_decl. */ + size_t old_len = (struct_decl ? strlen (struct_decl) : 0); + size_t line_len = line_end - line; + size_t new_len = old_len + line_len + 1; + char *new_struct_decl = new char[new_len]; + if (old_len > 0) + memcpy (new_struct_decl, struct_decl, old_len); + memcpy (new_struct_decl + old_len, line, line_len); + new_struct_decl[old_len + line_len] = '\0'; + if (struct_decl) + delete[] struct_decl; + struct_decl = new_struct_decl; + /* Append the lineno to struct_decl_linenos. */ + unsigned int *new_struct_decl_linenos = + new unsigned int[struct_decl_linecount + 1]; + if (struct_decl_linecount > 0) + memcpy (new_struct_decl_linenos, struct_decl_linenos, + struct_decl_linecount * sizeof (unsigned int)); + new_struct_decl_linenos[struct_decl_linecount] = lineno; + if (struct_decl_linenos) + delete[] struct_decl_linenos; + struct_decl_linenos = new_struct_decl_linenos; + /* Increment struct_decl_linecount. */ + struct_decl_linecount++; + } + lineno++; + line = line_end; + } + if (_verbatim_declarations != NULL && _verbatim_declarations_end == NULL) + { + fprintf (stderr, "%s:%u: unterminated %%{ section\n", + pretty_input_file_name (), _verbatim_declarations_lineno); + exit (1); + } + + /* Determine _struct_decl, _return_type, _struct_tag. */ + if (option[TYPE]) + { + if (struct_decl) + { + /* Drop leading whitespace and comments. */ + { + char *p = struct_decl; + unsigned int *l = struct_decl_linenos; + for (;;) + { + if (p[0] == ' ' || p[0] == '\t') + { + p++; + continue; + } + if (p[0] == '\n') + { + l++; + p++; + continue; + } + if (p[0] == '/') + { + if (p[1] == '*') + { + /* Skip over ANSI C style comment. */ + p += 2; + while (p[0] != '\0') + { + if (p[0] == '*' && p[1] == '/') + { + p += 2; + break; + } + if (p[0] == '\n') + l++; + p++; + } + continue; + } + if (p[1] == '/') + { + /* Skip over ISO C99 or C++ style comment. */ + p += 2; + while (p[0] != '\0' && p[0] != '\n') + p++; + if (p[0] == '\n') + { + l++; + p++; + } + continue; + } + } + break; + } + if (p != struct_decl) + { + size_t len = strlen (p); + char *new_struct_decl = new char[len + 1]; + memcpy (new_struct_decl, p, len + 1); + delete[] struct_decl; + struct_decl = new_struct_decl; + } + _struct_decl_lineno = *l; + } + /* Drop trailing whitespace. */ + for (char *p = struct_decl + strlen (struct_decl); p > struct_decl;) + if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t') + *--p = '\0'; + else + break; + } + if (struct_decl == NULL || struct_decl[0] == '\0') + { + fprintf (stderr, "%s: missing struct declaration" + " for option --struct-type\n", + pretty_input_file_name ()); + exit (1); + } + { + /* Ensure trailing semicolon. */ + size_t old_len = strlen (struct_decl); + if (struct_decl[old_len - 1] != ';') + { + char *new_struct_decl = new char[old_len + 2]; + memcpy (new_struct_decl, struct_decl, old_len); + new_struct_decl[old_len] = ';'; + new_struct_decl[old_len + 1] = '\0'; + delete[] struct_decl; + struct_decl = new_struct_decl; + } + } + /* Set _struct_decl to the entire declaration. */ + _struct_decl = struct_decl; + /* Set _struct_tag to the naked "struct something". */ + const char *p; + for (p = struct_decl; *p && *p != '{' && *p != ';' && *p != '\n'; p++) + ; + for (; p > struct_decl;) + if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t') + --p; + else + break; + size_t struct_tag_length = p - struct_decl; + char *struct_tag = new char[struct_tag_length + 1]; + memcpy (struct_tag, struct_decl, struct_tag_length); + struct_tag[struct_tag_length] = '\0'; + _struct_tag = struct_tag; + /* The return type of the lookup function is "struct something *". + No "const" here, because if !option[CONST], some user code might + want to modify the structure. */ + char *return_type = new char[struct_tag_length + 3]; + memcpy (return_type, struct_decl, struct_tag_length); + return_type[struct_tag_length] = ' '; + return_type[struct_tag_length + 1] = '*'; + return_type[struct_tag_length + 2] = '\0'; + _return_type = return_type; + } + + if (struct_decl_linenos) + delete[] struct_decl_linenos; + } + + /* Parse the keywords section. */ + { + Keyword_List **list_tail = &_head; + const char *delimiters = option.get_delimiters (); + unsigned int lineno = keywords_lineno; + bool charset_dependent = false; + for (const char *line = keywords; line < keywords_end; ) + { + const char *line_end; + line_end = (const char *) memchr (line, '\n', keywords_end - line); + if (line_end != NULL) + line_end++; + else + line_end = keywords_end; + + if (line[0] == '#') + ; /* Comment line. */ + else if (line[0] == '%') + { + fprintf (stderr, "%s:%u:" + " declarations are not allowed in the keywords section.\n" + "To declare a keyword starting with %%, enclose it in" + " double-quotes.\n", + pretty_input_file_name (), lineno); + exit (1); + } + else + { + /* An input line carrying a keyword. */ + const char *keyword; + size_t keyword_length; + const char *rest; + + if (line[0] == '"') + { + /* Parse a string in ANSI C syntax. */ + char *kp = new char[line_end-line]; + keyword = kp; + const char *lp = line + 1; + + for (;;) + { + if (lp == line_end) + { + fprintf (stderr, "%s:%u: unterminated string\n", + pretty_input_file_name (), lineno); + exit (1); + } + + char c = *lp; + if (c == '\\') + { + c = *++lp; + switch (c) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { + int code = 0; + int count = 0; + while (count < 3 && *lp >= '0' && *lp <= '7') + { + code = (code << 3) + (*lp - '0'); + lp++; + count++; + } + if (code > UCHAR_MAX) + fprintf (stderr, + "%s:%u: octal escape out of range\n", + pretty_input_file_name (), lineno); + *kp = static_cast(code); + break; + } + case 'x': + { + int code = 0; + int count = 0; + lp++; + while ((*lp >= '0' && *lp <= '9') + || (*lp >= 'A' && *lp <= 'F') + || (*lp >= 'a' && *lp <= 'f')) + { + code = (code << 4) + + (*lp >= 'A' && *lp <= 'F' + ? *lp - 'A' + 10 : + *lp >= 'a' && *lp <= 'f' + ? *lp - 'a' + 10 : + *lp - '0'); + lp++; + count++; + } + if (count == 0) + fprintf (stderr, "%s:%u: hexadecimal escape" + " without any hex digits\n", + pretty_input_file_name (), lineno); + if (code > UCHAR_MAX) + fprintf (stderr, "%s:%u: hexadecimal escape" + " out of range\n", + pretty_input_file_name (), lineno); + *kp = static_cast(code); + break; + } + case '\\': case '\'': case '"': + *kp = c; + lp++; + charset_dependent = true; + break; + case 'n': + *kp = '\n'; + lp++; + charset_dependent = true; + break; + case 't': + *kp = '\t'; + lp++; + charset_dependent = true; + break; + case 'r': + *kp = '\r'; + lp++; + charset_dependent = true; + break; + case 'f': + *kp = '\f'; + lp++; + charset_dependent = true; + break; + case 'b': + *kp = '\b'; + lp++; + charset_dependent = true; + break; + case 'a': + *kp = '\a'; + lp++; + charset_dependent = true; + break; + case 'v': + *kp = '\v'; + lp++; + charset_dependent = true; + break; + default: + fprintf (stderr, "%s:%u: invalid escape sequence" + " in string\n", + pretty_input_file_name (), lineno); + exit (1); + } + } + else if (c == '"') + break; + else + { + *kp = c; + lp++; + charset_dependent = true; + } + kp++; + } + lp++; + if (lp < line_end && *lp != '\n') + { + if (strchr (delimiters, *lp) == NULL) + { + fprintf (stderr, "%s:%u: string not followed" + " by delimiter\n", + pretty_input_file_name (), lineno); + exit (1); + } + lp++; + } + keyword_length = kp - keyword; + if (option[TYPE]) + { + char *line_rest = new char[line_end - lp + 1]; + memcpy (line_rest, lp, line_end - lp); + line_rest[line_end - lp - + (line_end > lp && line_end[-1] == '\n' ? 1 : 0)] + = '\0'; + rest = line_rest; + } + else + rest = empty_string; + } + else + { + /* Not a string. Look for the delimiter. */ + const char *lp = line; + for (;;) + { + if (!(lp < line_end && *lp != '\n')) + { + keyword = line; + keyword_length = lp - line; + rest = empty_string; + break; + } + if (strchr (delimiters, *lp) != NULL) + { + keyword = line; + keyword_length = lp - line; + lp++; + if (option[TYPE]) + { + char *line_rest = new char[line_end - lp + 1]; + memcpy (line_rest, lp, line_end - lp); + line_rest[line_end - lp - + (line_end > lp && line_end[-1] == '\n' + ? 1 : 0)] + = '\0'; + rest = line_rest; + } + else + rest = empty_string; + break; + } + lp++; + } + if (keyword_length > 0) + charset_dependent = true; + } + + /* Allocate Keyword and add it to the list. */ + Keyword *new_kw = _factory->create_keyword (keyword, keyword_length, + rest); + new_kw->_lineno = lineno; + *list_tail = new Keyword_List (new_kw); + list_tail = &(*list_tail)->rest(); + } + + lineno++; + line = line_end; + } + *list_tail = NULL; + + if (_head == NULL) + { + fprintf (stderr, "%s: No keywords in input file!\n", + pretty_input_file_name ()); + exit (1); + } + + _charset_dependent = charset_dependent; + } + + /* To be freed in the destructor. */ + _input = input; + _input_end = input_end; +} + +Input::~Input () +{ + /* Free allocated memory. */ + delete[] const_cast(_return_type); + delete[] const_cast(_struct_tag); + delete[] const_cast(_struct_decl); + delete[] _input; +} diff --git a/contrib/gperf-3.0.1/src/input.h b/contrib/gperf-3.0.1/src/input.h new file mode 100644 index 0000000000..5d51ab6110 --- /dev/null +++ b/contrib/gperf-3.0.1/src/input.h @@ -0,0 +1,69 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Input routines. + + Copyright (C) 1989-1998, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef input_h +#define input_h 1 + +#include +#include "keyword-list.h" + +class Input +{ +public: + Input (FILE *stream, Keyword_Factory *keyword_factory); + ~Input (); + void read_input (); +private: + /* Input stream. */ + FILE * _stream; + /* Creates the keywords. */ + Keyword_Factory * const _factory; +public: + /* Memory block containing the entire input. */ + char * _input; + char * _input_end; + /* The C code from the declarations section. */ + const char * _verbatim_declarations; + const char * _verbatim_declarations_end; + unsigned int _verbatim_declarations_lineno; + /* The C code from the end of the file. */ + const char * _verbatim_code; + const char * _verbatim_code_end; + unsigned int _verbatim_code_lineno; + /* Declaration of struct type for a keyword and its attributes. */ + const char * _struct_decl; + unsigned int _struct_decl_lineno; + /* Return type of the lookup function. */ + const char * _return_type; + /* Shorthand for user-defined struct tag type. */ + const char * _struct_tag; + /* List of all keywords. */ + Keyword_List * _head; + /* Whether the keyword chars would have different values in a different + character set. */ + bool _charset_dependent; +}; + +#endif diff --git a/contrib/gperf-3.0.1/src/keyword-list.cc b/contrib/gperf-3.0.1/src/keyword-list.cc new file mode 100644 index 0000000000..d4b55f9ce5 --- /dev/null +++ b/contrib/gperf-3.0.1/src/keyword-list.cc @@ -0,0 +1,175 @@ +/* Keyword list. + + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "keyword-list.h" + +#include + +/* -------------------------- Keyword_List class --------------------------- */ + +/* Constructor. */ +Keyword_List::Keyword_List (Keyword *car) + : _cdr (NULL), _car (car) +{ +} + +/* ------------------------- KeywordExt_List class ------------------------- */ + +/* Constructor. */ +KeywordExt_List::KeywordExt_List (KeywordExt *car) + : Keyword_List (car) +{ +} + +/* ------------------------ Keyword_List functions ------------------------- */ + +/* Copies a linear list, sharing the list elements. */ +Keyword_List * +copy_list (Keyword_List *list) +{ + Keyword_List *result; + Keyword_List **lastp = &result; + while (list != NULL) + { + Keyword_List *new_cons = new Keyword_List (list->first()); + *lastp = new_cons; + lastp = &new_cons->rest(); + list = list->rest(); + } + *lastp = NULL; + return result; +} + +/* Copies a linear list, sharing the list elements. */ +KeywordExt_List * +copy_list (KeywordExt_List *list) +{ + return static_cast (copy_list (static_cast (list))); +} + +/* Deletes a linear list, keeping the list elements in memory. */ +void +delete_list (Keyword_List *list) +{ + while (list != NULL) + { + Keyword_List *rest = list->rest(); + delete list; + list = rest; + } +} + +/* Type of a comparison function. */ +typedef bool (*Keyword_Comparison) (Keyword *keyword1, Keyword *keyword2); + +/* Merges two sorted lists together to form one sorted list. */ +static Keyword_List * +merge (Keyword_List *list1, Keyword_List *list2, Keyword_Comparison less) +{ + Keyword_List *result; + Keyword_List **resultp = &result; + for (;;) + { + if (!list1) + { + *resultp = list2; + break; + } + if (!list2) + { + *resultp = list1; + break; + } + if (less (list2->first(), list1->first())) + { + *resultp = list2; + resultp = &list2->rest(); + /* We would have a stable sorting if the next line would read: + list2 = *resultp; */ + list2 = list1; list1 = *resultp; + } + else + { + *resultp = list1; + resultp = &list1->rest(); + list1 = *resultp; + } + } + return result; +} + +/* Sorts a linear list, given a comparison function. + Note: This uses a variant of mergesort that is *not* a stable sorting + algorithm. */ +Keyword_List * +mergesort_list (Keyword_List *list, Keyword_Comparison less) +{ + if (list == NULL || list->rest() == NULL) + /* List of length 0 or 1. Nothing to do. */ + return list; + else + { + /* Determine a list node in the middle. */ + Keyword_List *middle = list; + for (Keyword_List *temp = list->rest();;) + { + temp = temp->rest(); + if (temp == NULL) + break; + temp = temp->rest(); + middle = middle->rest(); + if (temp == NULL) + break; + } + + /* Cut the list into two halves. + If the list has n elements, the left half has ceiling(n/2) elements + and the right half has floor(n/2) elements. */ + Keyword_List *right_half = middle->rest(); + middle->rest() = NULL; + + /* Sort the two halves, then merge them. */ + return merge (mergesort_list (list, less), + mergesort_list (right_half, less), + less); + } +} + +KeywordExt_List * +mergesort_list (KeywordExt_List *list, + bool (*less) (KeywordExt *keyword1, KeywordExt *keyword2)) +{ + return + static_cast + (mergesort_list (static_cast (list), + reinterpret_cast (less))); +} + + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "keyword-list.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/contrib/gperf-3.0.1/src/keyword-list.h b/contrib/gperf-3.0.1/src/keyword-list.h new file mode 100644 index 0000000000..d37102282b --- /dev/null +++ b/contrib/gperf-3.0.1/src/keyword-list.h @@ -0,0 +1,85 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Keyword list. + + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef keyword_list_h +#define keyword_list_h 1 + +#include "keyword.h" + +/* List node of a linear list of Keyword. */ +class Keyword_List +{ +public: + /* Constructor. */ + Keyword_List (Keyword *car); + + /* Access to first element of list. */ + Keyword * first () const; + /* Access to next element of list. */ + Keyword_List *& rest (); + +protected: + Keyword_List * _cdr; + Keyword * const _car; +}; + +/* List node of a linear list of KeywordExt. */ +class KeywordExt_List : public Keyword_List +{ +public: + /* Constructor. */ + KeywordExt_List (KeywordExt *car); + + /* Access to first element of list. */ + KeywordExt * first () const; + /* Access to next element of list. */ + KeywordExt_List *& rest (); +}; + +/* Copies a linear list, sharing the list elements. */ +extern Keyword_List * copy_list (Keyword_List *list); +extern KeywordExt_List * copy_list (KeywordExt_List *list); + +/* Deletes a linear list, keeping the list elements in memory. */ +extern void delete_list (Keyword_List *list); + +/* Sorts a linear list, given a comparison function. + Note: This uses a variant of mergesort that is *not* a stable sorting + algorithm. */ +extern Keyword_List * mergesort_list (Keyword_List *list, + bool (*less) (Keyword *keyword1, + Keyword *keyword2)); +extern KeywordExt_List * mergesort_list (KeywordExt_List *list, + bool (*less) (KeywordExt *keyword1, + KeywordExt *keyword2)); + +#ifdef __OPTIMIZE__ + +#define INLINE inline +#include "keyword-list.icc" +#undef INLINE + +#endif + +#endif diff --git a/contrib/gperf-3.0.1/src/keyword-list.icc b/contrib/gperf-3.0.1/src/keyword-list.icc new file mode 100644 index 0000000000..5c17a1937d --- /dev/null +++ b/contrib/gperf-3.0.1/src/keyword-list.icc @@ -0,0 +1,53 @@ +/* Inline Functions for keyword-list.{h,cc}. + + Copyright (C) 2002-2003 Free Software Foundation, Inc. + Written by Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* -------------------------- Keyword_List class --------------------------- */ + +/* Access to first element of list. */ +INLINE Keyword * +Keyword_List::first () const +{ + return _car; +} + +/* Access to next element of list. */ +INLINE Keyword_List *& +Keyword_List::rest () +{ + return _cdr; +} + +/* ------------------------- KeywordExt_List class ------------------------- */ + +/* Access to first element of list. */ +INLINE KeywordExt * +KeywordExt_List::first () const +{ + return static_cast(_car); +} + +/* Access to next element of list. */ +INLINE KeywordExt_List *& +KeywordExt_List::rest () +{ + return *reinterpret_cast(&_cdr); +} diff --git a/contrib/gperf-3.0.1/src/keyword.cc b/contrib/gperf-3.0.1/src/keyword.cc new file mode 100644 index 0000000000..fbf1a0afe7 --- /dev/null +++ b/contrib/gperf-3.0.1/src/keyword.cc @@ -0,0 +1,161 @@ +/* Keyword data. + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "keyword.h" + +#include +#include +#include +#include "positions.h" + + +/* --------------------------- KeywordExt class --------------------------- */ + +/* Sort a small set of 'unsigned int', base[0..len-1], in place. */ +static inline void sort_char_set (unsigned int *base, int len) +{ + /* Bubble sort is sufficient here. */ + for (int i = 1; i < len; i++) + { + int j; + unsigned int tmp; + + for (j = i, tmp = base[j]; j > 0 && tmp < base[j - 1]; j--) + base[j] = base[j - 1]; + + base[j] = tmp; + } +} + +/* Initializes selchars and selchars_length. + + General idea: + The hash function will be computed as + asso_values[allchars[key_pos[0]]] + + asso_values[allchars[key_pos[1]]] + ... + We compute selchars as the multiset + { allchars[key_pos[0]], allchars[key_pos[1]], ... } + so that the hash function becomes + asso_values[selchars[0]] + asso_values[selchars[1]] + ... + Furthermore we sort the selchars array, to ease detection of duplicates + later. + + More in detail: The arguments alpha_unify (used for case-insensitive + hash functions) and alpha_inc (used to disambiguate permutations) + apply slight modifications. The hash function will be computed as + sum (j=0,1,...: k = key_pos[j]: + asso_values[alpha_unify[allchars[k]+alpha_inc[k]]]) + + (allchars_length if !option[NOLENGTH], 0 otherwise). + We compute selchars as the multiset + { alpha_unify[allchars[k]+alpha_inc[k]] : j=0,1,..., k = key_pos[j] } + so that the hash function becomes + asso_values[selchars[0]] + asso_values[selchars[1]] + ... + + (allchars_length if !option[NOLENGTH], 0 otherwise). + */ + +unsigned int * +KeywordExt::init_selchars_low (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc) +{ + /* Iterate through the list of positions, initializing selchars + (via ptr). */ + PositionIterator iter = positions.iterator(_allchars_length); + + unsigned int *key_set = new unsigned int[iter.remaining()]; + unsigned int *ptr = key_set; + + for (int i; (i = iter.next ()) != PositionIterator::EOS; ) + { + unsigned int c; + if (i == Positions::LASTCHAR) + /* Special notation for last KEY position, i.e. '$'. */ + c = static_cast(_allchars[_allchars_length - 1]); + else if (i < _allchars_length) + { + /* Within range of KEY length, so we'll keep it. */ + c = static_cast(_allchars[i]); + if (alpha_inc) + c += alpha_inc[i]; + } + else + /* Out of range of KEY length, the iterator should not have + produced this. */ + abort (); + if (alpha_unify) + c = alpha_unify[c]; + *ptr = c; + ptr++; + } + + _selchars = key_set; + _selchars_length = ptr - key_set; + + return key_set; +} + +void +KeywordExt::init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify) +{ + init_selchars_low (positions, alpha_unify, NULL); +} + +void +KeywordExt::init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc) +{ + unsigned int *selchars = + init_selchars_low (positions, alpha_unify, alpha_inc); + + /* Sort the selchars elements alphabetically. */ + sort_char_set (selchars, _selchars_length); +} + +/* Deletes selchars. */ +void +KeywordExt::delete_selchars () +{ + delete[] const_cast(_selchars); +} + + +/* ------------------------- Keyword_Factory class ------------------------- */ + +Keyword_Factory::Keyword_Factory () +{ +} + +Keyword_Factory::~Keyword_Factory () +{ +} + + +/* ------------------------------------------------------------------------- */ + +char empty_string[1] = ""; + + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "keyword.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/contrib/gperf-3.0.1/src/keyword.h b/contrib/gperf-3.0.1/src/keyword.h new file mode 100644 index 0000000000..c0e2156773 --- /dev/null +++ b/contrib/gperf-3.0.1/src/keyword.h @@ -0,0 +1,116 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Keyword data. + + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef keyword_h +#define keyword_h 1 + +/* Class defined in "positions.h". */ +class Positions; + +/* An instance of this class is a keyword, as specified in the input file. */ + +struct Keyword +{ + /* Constructor. */ + Keyword (const char *allchars, int allchars_length, + const char *rest); + + /* Data members defined immediately by the input file. */ + /* The keyword as a string, possibly containing NUL bytes. */ + const char *const _allchars; + int const _allchars_length; + /* Additional stuff seen on the same line of the input file. */ + const char *const _rest; + /* Line number of this keyword in the input file. */ + unsigned int _lineno; +}; + +/* A keyword, in the context of a given keyposition list. */ + +struct KeywordExt : public Keyword +{ + /* Constructor. */ + KeywordExt (const char *allchars, int allchars_length, + const char *rest); + + /* Data members depending on the keyposition list. */ + /* The selected characters that participate for the hash function, + selected according to the keyposition list, as a canonically reordered + multiset. */ + const unsigned int * _selchars; + int _selchars_length; + /* Chained list of keywords having the same _selchars and + - if !option[NOLENGTH] - also the same _allchars_length. + Note that these duplicates are not members of the main keyword list. */ + KeywordExt * _duplicate_link; + + /* Methods depending on the keyposition list. */ + /* Initializes selchars and selchars_length, without reordering. */ + void init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify); + /* Initializes selchars and selchars_length, with reordering. */ + void init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc); + /* Deletes selchars. */ + void delete_selchars (); + + /* Data members used by the algorithm. */ + int _hash_value; /* Hash value for the keyword. */ + + /* Data members used by the output routines. */ + int _final_index; + +private: + unsigned int * init_selchars_low (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc); +}; + +/* An abstract factory for creating Keyword instances. + This factory is used to make the Input class independent of the concrete + class KeywordExt. */ + +class Keyword_Factory +{ +public: + /* Constructor. */ + Keyword_Factory (); + /* Destructor. */ + virtual ~Keyword_Factory (); + + /* Creates a new Keyword. */ + virtual /*abstract*/ Keyword * + create_keyword (const char *allchars, int allchars_length, + const char *rest) = 0; +}; + +/* A statically allocated empty string. */ +extern char empty_string[1]; + +#ifdef __OPTIMIZE__ + +#define INLINE inline +#include "keyword.icc" +#undef INLINE + +#endif + +#endif diff --git a/contrib/gperf-3.0.1/src/keyword.icc b/contrib/gperf-3.0.1/src/keyword.icc new file mode 100644 index 0000000000..baa61d739d --- /dev/null +++ b/contrib/gperf-3.0.1/src/keyword.icc @@ -0,0 +1,42 @@ +/* Inline Functions for keyword.{h,cc}. + + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* ----------------------------- Keyword class ----------------------------- */ + +/* Constructor. */ +INLINE +Keyword::Keyword (const char *allchars, int allchars_length, const char *rest) + : _allchars (allchars), _allchars_length (allchars_length), _rest (rest) +{ +} + + +/* --------------------------- KeywordExt class --------------------------- */ + +/* Constructor. */ +INLINE +KeywordExt::KeywordExt (const char *allchars, int allchars_length, const char *rest) + : Keyword (allchars, allchars_length, rest), + _final_index (-1) +{ +} diff --git a/contrib/gperf-3.0.1/src/main.cc b/contrib/gperf-3.0.1/src/main.cc new file mode 100644 index 0000000000..7245b4064d --- /dev/null +++ b/contrib/gperf-3.0.1/src/main.cc @@ -0,0 +1,155 @@ +/* Driver program for the hash function generator + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "options.h" +#include "input.h" +#include "search.h" +#include "output.h" + + +/* ------------------------------------------------------------------------- */ + +/* This Keyword factory produces KeywordExt instances. */ + +class KeywordExt_Factory : public Keyword_Factory +{ +virtual Keyword * create_keyword (const char *allchars, int allchars_length, + const char *rest); +}; + +Keyword * +KeywordExt_Factory::create_keyword (const char *allchars, int allchars_length, const char *rest) +{ + return new KeywordExt (allchars, allchars_length, rest); +} + +/* ------------------------------------------------------------------------- */ + +int +main (int argc, char *argv[]) +{ + int exitcode; + + /* Set the Options. Open the input file and assign stdin to it. */ + option.parse_options (argc, argv); + + /* Open the input file. */ + if (option.get_input_file_name ()) + if (!freopen (option.get_input_file_name (), "r", stdin)) + { + fprintf (stderr, "Cannot open input file '%s'\n", + option.get_input_file_name ()); + exit (1); + } + + { + /* Initialize the keyword list. */ + KeywordExt_Factory factory; + Input inputter (stdin, &factory); + inputter.read_input (); + /* We can cast the keyword list to KeywordExt_List* because its list + elements were created by KeywordExt_Factory. */ + KeywordExt_List* list = static_cast(inputter._head); + + { + /* Search for a good hash function. */ + Search searcher (list); + searcher.optimize (); + list = searcher._head; + + /* Open the output file. */ + if (option.get_output_file_name ()) + if (strcmp (option.get_output_file_name (), "-") != 0) + if (!freopen (option.get_output_file_name (), "w", stdout)) + { + fprintf (stderr, "Cannot open output file '%s'\n", + option.get_output_file_name ()); + exit (1); + } + + { + /* Output the hash function code. */ + Output outputter (searcher._head, + inputter._struct_decl, + inputter._struct_decl_lineno, + inputter._return_type, + inputter._struct_tag, + inputter._verbatim_declarations, + inputter._verbatim_declarations_end, + inputter._verbatim_declarations_lineno, + inputter._verbatim_code, + inputter._verbatim_code_end, + inputter._verbatim_code_lineno, + inputter._charset_dependent, + searcher._total_keys, + searcher._max_key_len, + searcher._min_key_len, + searcher._key_positions, + searcher._alpha_inc, + searcher._total_duplicates, + searcher._alpha_size, + searcher._asso_values); + outputter.output (); + + /* Check for write error on stdout. */ + exitcode = 0; + if (fflush (stdout) || ferror (stdout)) + { + fprintf (stderr, "error while writing output file\n"); + exitcode = 1; + } + + /* Here we run the Output destructor. */ + } + /* Here we run the Search destructor. */ + } + + /* Also delete the list that was allocated inside Input and reordered + inside Search. */ + for (KeywordExt_List *ptr = list; ptr; ptr = ptr->rest()) + { + KeywordExt *keyword = ptr->first(); + do + { + KeywordExt *next_keyword = keyword->_duplicate_link; + delete[] const_cast(keyword->_selchars); + if (keyword->_rest != empty_string) + delete[] const_cast(keyword->_rest); + if (!(keyword->_allchars >= inputter._input + && keyword->_allchars < inputter._input_end)) + delete[] const_cast(keyword->_allchars); + delete keyword; + keyword = next_keyword; + } + while (keyword != NULL); + } + delete_list (list); + + /* Here we run the Input destructor. */ + } + + /* Don't use exit() here, it skips the destructors. */ + return exitcode; +} diff --git a/contrib/gperf-3.0.1/src/options.cc b/contrib/gperf-3.0.1/src/options.cc new file mode 100644 index 0000000000..88ae9fca58 --- /dev/null +++ b/contrib/gperf-3.0.1/src/options.cc @@ -0,0 +1,1050 @@ +/* Handles parsing the Options provided to the user. + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "options.h" + +#include +#include /* declares atoi(), abs(), exit() */ +#include /* declares strcmp() */ +#include /* declares isdigit() */ +#include /* defines CHAR_MAX */ +#include "getopt.h" +#include "version.h" + +/* Global option coordinator for the entire program. */ +Options option; + +/* Records the program name. */ +const char *program_name; + +/* Size to jump on a collision. */ +static const int DEFAULT_JUMP_VALUE = 5; + +/* Default name for generated lookup function. */ +static const char *const DEFAULT_FUNCTION_NAME = "in_word_set"; + +/* Default name for the key component. */ +static const char *const DEFAULT_SLOT_NAME = "name"; + +/* Default struct initializer suffix. */ +static const char *const DEFAULT_INITIALIZER_SUFFIX = ""; + +/* Default name for the generated class. */ +static const char *const DEFAULT_CLASS_NAME = "Perfect_Hash"; + +/* Default name for generated hash function. */ +static const char *const DEFAULT_HASH_NAME = "hash"; + +/* Default name for generated hash table array. */ +static const char *const DEFAULT_WORDLIST_NAME = "wordlist"; + +/* Default name for string pool. */ +static const char *const DEFAULT_STRINGPOOL_NAME = "stringpool"; + +/* Default delimiters that separate keywords from their attributes. */ +static const char *const DEFAULT_DELIMITERS = ","; + +/* Prints program usage to given stream. */ + +void +Options::short_usage (FILE * stream) +{ + fprintf (stream, + "Try '%s --help' for more information.\n", program_name); +} + +void +Options::long_usage (FILE * stream) +{ + fprintf (stream, + "GNU 'gperf' generates perfect hash functions.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Usage: %s [OPTION]... [INPUT-FILE]\n", + program_name); + fprintf (stream, "\n"); + fprintf (stream, + "If a long option shows an argument as mandatory, then it is mandatory\n" + "for the equivalent short option also.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Output file location:\n"); + fprintf (stream, + " --output-file=FILE Write output to specified file.\n"); + fprintf (stream, + "The results are written to standard output if no output file is specified\n" + "or if it is -.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Input file interpretation:\n"); + fprintf (stream, + " -e, --delimiters=DELIMITER-LIST\n" + " Allow user to provide a string containing delimiters\n" + " used to separate keywords from their attributes.\n" + " Default is \",\".\n"); + fprintf (stream, + " -t, --struct-type Allows the user to include a structured type\n" + " declaration for generated code. Any text before %%%%\n" + " is considered part of the type declaration. Key\n" + " words and additional fields may follow this, one\n" + " group of fields per line.\n"); + fprintf (stream, + " --ignore-case Consider upper and lower case ASCII characters as\n" + " equivalent. Note that locale dependent case mappings\n" + " are ignored.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Language for the output code:\n"); + fprintf (stream, + " -L, --language=LANGUAGE-NAME\n" + " Generates code in the specified language. Languages\n" + " handled are currently C++, ANSI-C, C, and KR-C. The\n" + " default is C.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Details in the output code:\n"); + fprintf (stream, + " -K, --slot-name=NAME Select name of the keyword component in the keyword\n" + " structure.\n"); + fprintf (stream, + " -F, --initializer-suffix=INITIALIZERS\n" + " Initializers for additional components in the keyword\n" + " structure.\n"); + fprintf (stream, + " -H, --hash-function-name=NAME\n" + " Specify name of generated hash function. Default is\n" + " 'hash'.\n"); + fprintf (stream, + " -N, --lookup-function-name=NAME\n" + " Specify name of generated lookup function. Default\n" + " name is 'in_word_set'.\n"); + fprintf (stream, + " -Z, --class-name=NAME Specify name of generated C++ class. Default name is\n" + " 'Perfect_Hash'.\n"); + fprintf (stream, + " -7, --seven-bit Assume 7-bit characters.\n"); + fprintf (stream, + " -l, --compare-lengths Compare key lengths before trying a string\n" + " comparison. This is necessary if the keywords\n" + " contain NUL bytes. It also helps cut down on the\n" + " number of string comparisons made during the lookup.\n"); + fprintf (stream, + " -c, --compare-strncmp Generate comparison code using strncmp rather than\n" + " strcmp.\n"); + fprintf (stream, + " -C, --readonly-tables Make the contents of generated lookup tables\n" + " constant, i.e., readonly.\n"); + fprintf (stream, + " -E, --enum Define constant values using an enum local to the\n" + " lookup function rather than with defines.\n"); + fprintf (stream, + " -I, --includes Include the necessary system include file \n" + " at the beginning of the code.\n"); + fprintf (stream, + " -G, --global-table Generate the static table of keywords as a static\n" + " global variable, rather than hiding it inside of the\n" + " lookup function (which is the default behavior).\n"); + fprintf (stream, + " -P, --pic Optimize the generated table for inclusion in shared\n" + " libraries. This reduces the startup time of programs\n" + " using a shared library containing the generated code.\n"); + fprintf (stream, + " -Q, --string-pool-name=NAME\n" + " Specify name of string pool generated by option --pic.\n" + " Default name is 'stringpool'.\n"); + fprintf (stream, + " --null-strings Use NULL strings instead of empty strings for empty\n" + " keyword table entries.\n"); + fprintf (stream, + " -W, --word-array-name=NAME\n" + " Specify name of word list array. Default name is\n" + " 'wordlist'.\n"); + fprintf (stream, + " -S, --switch=COUNT Causes the generated C code to use a switch\n" + " statement scheme, rather than an array lookup table.\n" + " This can lead to a reduction in both time and space\n" + " requirements for some keyfiles. The COUNT argument\n" + " determines how many switch statements are generated.\n" + " A value of 1 generates 1 switch containing all the\n" + " elements, a value of 2 generates 2 tables with 1/2\n" + " the elements in each table, etc. If COUNT is very\n" + " large, say 1000000, the generated C code does a\n" + " binary search.\n"); + fprintf (stream, + " -T, --omit-struct-type\n" + " Prevents the transfer of the type declaration to the\n" + " output file. Use this option if the type is already\n" + " defined elsewhere.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Algorithm employed by gperf:\n"); + fprintf (stream, + " -k, --key-positions=KEYS\n" + " Select the key positions used in the hash function.\n" + " The allowable choices range between 1-%d, inclusive.\n" + " The positions are separated by commas, ranges may be\n" + " used, and key positions may occur in any order.\n" + " Also, the meta-character '*' causes the generated\n" + " hash function to consider ALL key positions, and $\n" + " indicates the \"final character\" of a key, e.g.,\n" + " $,1,2,4,6-10.\n", + Positions::MAX_KEY_POS); + fprintf (stream, + " -D, --duplicates Handle keywords that hash to duplicate values. This\n" + " is useful for certain highly redundant keyword sets.\n"); + fprintf (stream, + " -m, --multiple-iterations=ITERATIONS\n" + " Perform multiple choices of the -i and -j values,\n" + " and choose the best results. This increases the\n" + " running time by a factor of ITERATIONS but does a\n" + " good job minimizing the generated table size.\n"); + fprintf (stream, + " -i, --initial-asso=N Provide an initial value for the associate values\n" + " array. Default is 0. Setting this value larger helps\n" + " inflate the size of the final table.\n"); + fprintf (stream, + " -j, --jump=JUMP-VALUE Affects the \"jump value\", i.e., how far to advance\n" + " the associated character value upon collisions. Must\n" + " be an odd number, default is %d.\n", + DEFAULT_JUMP_VALUE); + fprintf (stream, + " -n, --no-strlen Do not include the length of the keyword when\n" + " computing the hash function.\n"); + fprintf (stream, + " -r, --random Utilizes randomness to initialize the associated\n" + " values table.\n"); + fprintf (stream, + " -s, --size-multiple=N Affects the size of the generated hash table. The\n" + " numeric argument N indicates \"how many times larger\n" + " or smaller\" the associated value range should be,\n" + " in relationship to the number of keys, e.g. a value\n" + " of 3 means \"allow the maximum associated value to\n" + " be about 3 times larger than the number of input\n" + " keys\". Conversely, a value of 1/3 means \"make the\n" + " maximum associated value about 3 times smaller than\n" + " the number of input keys\". A larger table should\n" + " decrease the time required for an unsuccessful\n" + " search, at the expense of extra table space. Default\n" + " value is 1.\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Informative output:\n" + " -h, --help Print this message.\n" + " -v, --version Print the gperf version number.\n" + " -d, --debug Enables the debugging option (produces verbose\n" + " output to the standard error).\n"); + fprintf (stream, "\n"); + fprintf (stream, + "Report bugs to .\n"); +} + +/* Prints the given options. */ + +void +Options::print_options () const +{ + printf ("/* Command-line: "); + + for (int i = 0; i < _argument_count; i++) + { + const char *arg = _argument_vector[i]; + + /* Escape arg if it contains shell metacharacters. */ + if (*arg == '-') + { + putchar (*arg); + arg++; + if (*arg >= 'A' && *arg <= 'Z' || *arg >= 'a' && *arg <= 'z') + { + putchar (*arg); + arg++; + } + else if (*arg == '-') + { + do + { + putchar (*arg); + arg++; + } + while (*arg >= 'A' && *arg <= 'Z' || *arg >= 'a' && *arg <= 'z' || *arg == '-'); + if (*arg == '=') + { + putchar (*arg); + arg++; + } + } + } + if (strpbrk (arg, "\t\n !\"#$&'()*;<>?[\\]`{|}~") != NULL) + { + if (strchr (arg, '\'') != NULL) + { + putchar ('"'); + for (; *arg; arg++) + { + if (*arg == '\"' || *arg == '\\' || *arg == '$' || *arg == '`') + putchar ('\\'); + putchar (*arg); + } + putchar ('"'); + } + else + { + putchar ('\''); + for (; *arg; arg++) + { + if (*arg == '\\') + putchar ('\\'); + putchar (*arg); + } + putchar ('\''); + } + } + else + printf ("%s", arg); + + printf (" "); + } + + printf (" */"); +} + +/* ------------------------------------------------------------------------- */ + +/* Parses a string denoting key positions. */ + +class PositionStringParser +{ +public: + /* Initializes a key position string parser for string STR. */ + PositionStringParser (const char *str, + int low_bound, int high_bound, + int end_word_marker, int error_value, int end_marker); + /* Returns the next key position from the given string. */ + int nextPosition (); +private: + /* A pointer to the string provided by the user. */ + const char * _str; + /* Smallest possible value, inclusive. */ + int const _low_bound; + /* Greatest possible value, inclusive. */ + int const _high_bound; + /* A value marking the abstract "end of word" ( usually '$'). */ + int const _end_word_marker; + /* Error value returned when input is syntactically erroneous. */ + int const _error_value; + /* Value returned after last key is processed. */ + int const _end_marker; + /* Intermediate state for producing a range of positions. */ + bool _in_range; /* True while producing a range of positions. */ + int _range_upper_bound; /* Upper bound (inclusive) of the range. */ + int _range_curr_value; /* Last value returned. */ +}; + +/* Initializes a key position strng parser for string STR. */ +PositionStringParser::PositionStringParser (const char *str, + int low_bound, int high_bound, + int end_word_marker, int error_value, int end_marker) + : _str (str), + _low_bound (low_bound), + _high_bound (high_bound), + _end_word_marker (end_word_marker), + _error_value (error_value), + _end_marker (end_marker), + _in_range (false) +{ +} + +/* Returns the next key position from the given string. */ +int +PositionStringParser::nextPosition () +{ + if (_in_range) + { + /* We are inside a range. Return the next value from the range. */ + if (++_range_curr_value >= _range_upper_bound) + _in_range = false; + return _range_curr_value; + } + else + { + /* Continue parsing the given string. */ + while (*_str) + switch (*_str) + { + case ',': + /* Skip the comma. */ + _str++; + break; + case '$': + /* Valid key position. */ + _str++; + return _end_word_marker; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + /* Valid key position. */ + { + int curr_value; + for (curr_value = 0; isdigit (static_cast(*_str)); _str++) + curr_value = curr_value * 10 + (*_str - '0'); + + if (*_str == '-') + { + _str++; + /* Starting a range of key positions. */ + _in_range = true; + + for (_range_upper_bound = 0; + isdigit (static_cast(*_str)); + _str++) + _range_upper_bound = _range_upper_bound * 10 + (*_str - '0'); + + /* Verify range's upper bound. */ + if (!(_range_upper_bound > curr_value && _range_upper_bound <= _high_bound)) + return _error_value; + _range_curr_value = curr_value; + } + + /* Verify range's lower bound. */ + if (!(curr_value >= _low_bound && curr_value <= _high_bound)) + return _error_value; + return curr_value; + } + default: + /* Invalid syntax. */ + return _error_value; + } + + return _end_marker; + } +} + +/* ------------------------------------------------------------------------- */ + +/* Sets the default Options. */ + +Options::Options () + : _option_word (C), + _input_file_name (NULL), + _output_file_name (NULL), + _language (NULL), + _jump (DEFAULT_JUMP_VALUE), + _initial_asso_value (0), + _asso_iterations (0), + _total_switches (1), + _size_multiple (1), + _function_name (DEFAULT_FUNCTION_NAME), + _slot_name (DEFAULT_SLOT_NAME), + _initializer_suffix (DEFAULT_INITIALIZER_SUFFIX), + _class_name (DEFAULT_CLASS_NAME), + _hash_name (DEFAULT_HASH_NAME), + _wordlist_name (DEFAULT_WORDLIST_NAME), + _stringpool_name (DEFAULT_STRINGPOOL_NAME), + _delimiters (DEFAULT_DELIMITERS), + _key_positions () +{ +} + +/* Dumps option status when debugging is enabled. */ + +Options::~Options () +{ + if (_option_word & DEBUG) + { + fprintf (stderr, "\ndumping Options:" + "\nTYPE is........: %s" + "\nUPPERLOWER is..: %s" + "\nKRC is.........: %s" + "\nC is...........: %s" + "\nANSIC is.......: %s" + "\nCPLUSPLUS is...: %s" + "\nSEVENBIT is....: %s" + "\nLENTABLE is....: %s" + "\nCOMP is........: %s" + "\nCONST is.......: %s" + "\nENUM is........: %s" + "\nINCLUDE is.....: %s" + "\nGLOBAL is......: %s" + "\nNULLSTRINGS is.: %s" + "\nSHAREDLIB is...: %s" + "\nSWITCH is......: %s" + "\nNOTYPE is......: %s" + "\nDUP is.........: %s" + "\nNOLENGTH is....: %s" + "\nRANDOM is......: %s" + "\nDEBUG is.......: %s" + "\nlookup function name = %s" + "\nhash function name = %s" + "\nword list name = %s" + "\nstring pool name = %s" + "\nslot name = %s" + "\ninitializer suffix = %s" + "\nasso_values iterations = %d" + "\njump value = %d" + "\nhash table size multiplier = %g" + "\ninitial associated value = %d" + "\ndelimiters = %s" + "\nnumber of switch statements = %d\n", + _option_word & TYPE ? "enabled" : "disabled", + _option_word & UPPERLOWER ? "enabled" : "disabled", + _option_word & KRC ? "enabled" : "disabled", + _option_word & C ? "enabled" : "disabled", + _option_word & ANSIC ? "enabled" : "disabled", + _option_word & CPLUSPLUS ? "enabled" : "disabled", + _option_word & SEVENBIT ? "enabled" : "disabled", + _option_word & LENTABLE ? "enabled" : "disabled", + _option_word & COMP ? "enabled" : "disabled", + _option_word & CONST ? "enabled" : "disabled", + _option_word & ENUM ? "enabled" : "disabled", + _option_word & INCLUDE ? "enabled" : "disabled", + _option_word & GLOBAL ? "enabled" : "disabled", + _option_word & NULLSTRINGS ? "enabled" : "disabled", + _option_word & SHAREDLIB ? "enabled" : "disabled", + _option_word & SWITCH ? "enabled" : "disabled", + _option_word & NOTYPE ? "enabled" : "disabled", + _option_word & DUP ? "enabled" : "disabled", + _option_word & NOLENGTH ? "enabled" : "disabled", + _option_word & RANDOM ? "enabled" : "disabled", + _option_word & DEBUG ? "enabled" : "disabled", + _function_name, _hash_name, _wordlist_name, _stringpool_name, + _slot_name, _initializer_suffix, _asso_iterations, _jump, + _size_multiple, _initial_asso_value, _delimiters, + _total_switches); + if (_key_positions.is_useall()) + fprintf (stderr, "all characters are used in the hash function\n"); + else + { + fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n", + _key_positions.get_size()); + + PositionIterator iter = _key_positions.iterator(); + for (int pos; (pos = iter.next()) != PositionIterator::EOS; ) + if (pos == Positions::LASTCHAR) + fprintf (stderr, "$\n"); + else + fprintf (stderr, "%d\n", pos + 1); + } + + fprintf (stderr, "finished dumping Options\n"); + } +} + + +/* Sets the output language, if not already set. */ +void +Options::set_language (const char *language) +{ + if (_language == NULL) + { + _language = language; + _option_word &= ~(KRC | C | ANSIC | CPLUSPLUS); + if (!strcmp (language, "KR-C")) + _option_word |= KRC; + else if (!strcmp (language, "C")) + _option_word |= C; + else if (!strcmp (language, "ANSI-C")) + _option_word |= ANSIC; + else if (!strcmp (language, "C++")) + _option_word |= CPLUSPLUS; + else + { + fprintf (stderr, "unsupported language option %s, defaulting to C\n", + language); + _option_word |= C; + } + } +} + +/* Sets the total number of switch statements, if not already set. */ +void +Options::set_total_switches (int total_switches) +{ + if (!(_option_word & SWITCH)) + { + _option_word |= SWITCH; + _total_switches = total_switches; + } +} + +/* Sets the generated function name, if not already set. */ +void +Options::set_function_name (const char *name) +{ + if (_function_name == DEFAULT_FUNCTION_NAME) + _function_name = name; +} + +/* Sets the keyword key name, if not already set. */ +void +Options::set_slot_name (const char *name) +{ + if (_slot_name == DEFAULT_SLOT_NAME) + _slot_name = name; +} + +/* Sets the struct initializer suffix, if not already set. */ +void +Options::set_initializer_suffix (const char *initializers) +{ + if (_initializer_suffix == DEFAULT_INITIALIZER_SUFFIX) + _initializer_suffix = initializers; +} + +/* Sets the generated class name, if not already set. */ +void +Options::set_class_name (const char *name) +{ + if (_class_name == DEFAULT_CLASS_NAME) + _class_name = name; +} + +/* Sets the hash function name, if not already set. */ +void +Options::set_hash_name (const char *name) +{ + if (_hash_name == DEFAULT_HASH_NAME) + _hash_name = name; +} + +/* Sets the hash table array name, if not already set. */ +void +Options::set_wordlist_name (const char *name) +{ + if (_wordlist_name == DEFAULT_WORDLIST_NAME) + _wordlist_name = name; +} + +/* Sets the string pool name, if not already set. */ +void +Options::set_stringpool_name (const char *name) +{ + if (_stringpool_name == DEFAULT_STRINGPOOL_NAME) + _stringpool_name = name; +} + +/* Sets the delimiters string, if not already set. */ +void +Options::set_delimiters (const char *delimiters) +{ + if (_delimiters == DEFAULT_DELIMITERS) + _delimiters = delimiters; +} + + +/* Parses the command line Options and sets appropriate flags in option_word. */ + +static const struct option long_options[] = +{ + { "output-file", required_argument, NULL, CHAR_MAX + 1 }, + { "ignore-case", no_argument, NULL, CHAR_MAX + 2 }, + { "delimiters", required_argument, NULL, 'e' }, + { "struct-type", no_argument, NULL, 't' }, + { "language", required_argument, NULL, 'L' }, + { "slot-name", required_argument, NULL, 'K' }, + { "initializer-suffix", required_argument, NULL, 'F' }, + { "hash-fn-name", required_argument, NULL, 'H' }, /* backward compatibility */ + { "hash-function-name", required_argument, NULL, 'H' }, + { "lookup-fn-name", required_argument, NULL, 'N' }, /* backward compatibility */ + { "lookup-function-name", required_argument, NULL, 'N' }, + { "class-name", required_argument, NULL, 'Z' }, + { "seven-bit", no_argument, NULL, '7' }, + { "compare-strncmp", no_argument, NULL, 'c' }, + { "readonly-tables", no_argument, NULL, 'C' }, + { "enum", no_argument, NULL, 'E' }, + { "includes", no_argument, NULL, 'I' }, + { "global-table", no_argument, NULL, 'G' }, + { "word-array-name", required_argument, NULL, 'W' }, + { "switch", required_argument, NULL, 'S' }, + { "omit-struct-type", no_argument, NULL, 'T' }, + { "key-positions", required_argument, NULL, 'k' }, + { "compare-strlen", no_argument, NULL, 'l' }, /* backward compatibility */ + { "compare-lengths", no_argument, NULL, 'l' }, + { "duplicates", no_argument, NULL, 'D' }, + { "fast", required_argument, NULL, 'f' }, + { "initial-asso", required_argument, NULL, 'i' }, + { "jump", required_argument, NULL, 'j' }, + { "multiple-iterations", required_argument, NULL, 'm' }, + { "no-strlen", no_argument, NULL, 'n' }, + { "occurrence-sort", no_argument, NULL, 'o' }, + { "optimized-collision-resolution", no_argument, NULL, 'O' }, + { "pic", no_argument, NULL, 'P' }, + { "string-pool-name", required_argument, NULL, 'Q' }, + { "null-strings", no_argument, NULL, CHAR_MAX + 3 }, + { "random", no_argument, NULL, 'r' }, + { "size-multiple", required_argument, NULL, 's' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "debug", no_argument, NULL, 'd' }, + { NULL, no_argument, NULL, 0 } +}; + +void +Options::parse_options (int argc, char *argv[]) +{ + int option_char; + + program_name = argv[0]; + _argument_count = argc; + _argument_vector = argv; + + while ((option_char = + getopt_long (_argument_count, _argument_vector, + "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7", + long_options, NULL)) + != -1) + { + switch (option_char) + { + case 'a': /* Generated code uses the ANSI prototype format. */ + break; /* This is now the default. */ + case 'c': /* Generate strncmp rather than strcmp. */ + { + _option_word |= COMP; + break; + } + case 'C': /* Make the generated tables readonly (const). */ + { + _option_word |= CONST; + break; + } + case 'd': /* Enable debugging option. */ + { + _option_word |= DEBUG; + fprintf (stderr, "Starting program %s, version %s, with debugging on.\n", + program_name, version_string); + break; + } + case 'D': /* Enable duplicate option. */ + { + _option_word |= DUP; + break; + } + case 'e': /* Specify keyword/attribute separator */ + { + _delimiters = /*getopt*/optarg; + break; + } + case 'E': + { + _option_word |= ENUM; + break; + } + case 'f': /* Generate the hash table "fast". */ + break; /* Not needed any more. */ + case 'F': + { + _initializer_suffix = /*getopt*/optarg; + break; + } + case 'g': /* Use the 'inline' keyword for generated sub-routines, ifdef __GNUC__. */ + break; /* This is now the default. */ + case 'G': /* Make the keyword table a global variable. */ + { + _option_word |= GLOBAL; + break; + } + case 'h': /* Displays a list of helpful Options to the user. */ + { + long_usage (stdout); + exit (0); + } + case 'H': /* Sets the name for the hash function. */ + { + _hash_name = /*getopt*/optarg; + break; + } + case 'i': /* Sets the initial value for the associated values array. */ + { + if ((_initial_asso_value = atoi (/*getopt*/optarg)) < 0) + fprintf (stderr, "Initial value %d should be non-zero, ignoring and continuing.\n", _initial_asso_value); + if (option[RANDOM]) + fprintf (stderr, "warning, -r option superceeds -i, ignoring -i option and continuing\n"); + break; + } + case 'I': /* Enable #include statements. */ + { + _option_word |= INCLUDE; + break; + } + case 'j': /* Sets the jump value, must be odd for later algorithms. */ + { + if ((_jump = atoi (/*getopt*/optarg)) < 0) + { + fprintf (stderr, "Jump value %d must be a positive number.\n", _jump); + short_usage (stderr); + exit (1); + } + else if (_jump && ((_jump % 2) == 0)) + fprintf (stderr, "Jump value %d should be odd, adding 1 and continuing...\n", _jump++); + break; + } + case 'k': /* Sets key positions used for hash function. */ + { + _option_word |= POSITIONS; + const int BAD_VALUE = -3; + const int EOS = PositionIterator::EOS; + int value; + PositionStringParser sparser (/*getopt*/optarg, 1, Positions::MAX_KEY_POS, Positions::LASTCHAR, BAD_VALUE, EOS); + + if (/*getopt*/optarg [0] == '*') /* Use all the characters for hashing!!!! */ + _key_positions.set_useall(true); + else + { + _key_positions.set_useall(false); + int *key_positions = _key_positions.pointer(); + int *key_pos; + + for (key_pos = key_positions; (value = sparser.nextPosition()) != EOS; key_pos++) + { + if (value == BAD_VALUE) + { + fprintf (stderr, "Invalid position value or range, use 1,2,3-%d,'$' or '*'.\n", + Positions::MAX_KEY_POS); + short_usage (stderr); + exit (1); + } + if (key_pos - key_positions == Positions::MAX_SIZE) + { + /* More than Positions::MAX_SIZE key positions. + Since all key positions are in the range + 0..Positions::MAX_KEY_POS-1 or == Positions::LASTCHAR, + there must be duplicates. */ + fprintf (stderr, "Duplicate key positions selected\n"); + short_usage (stderr); + exit (1); + } + if (value != Positions::LASTCHAR) + /* We use 0-based indices in the class Positions. */ + value = value - 1; + *key_pos = value; + } + + unsigned int total_keysig_size = key_pos - key_positions; + if (total_keysig_size == 0) + { + fprintf (stderr, "No key positions selected.\n"); + short_usage (stderr); + exit (1); + } + _key_positions.set_size (total_keysig_size); + + /* Sorts the key positions *IN REVERSE ORDER!!* + This makes further routines more efficient. Especially + when generating code. */ + if (! _key_positions.sort()) + { + fprintf (stderr, "Duplicate key positions selected\n"); + short_usage (stderr); + exit (1); + } + } + break; + } + case 'K': /* Make this the keyname for the keyword component field. */ + { + _slot_name = /*getopt*/optarg; + break; + } + case 'l': /* Create length table to avoid extra string compares. */ + { + _option_word |= LENTABLE; + break; + } + case 'L': /* Deal with different generated languages. */ + { + _language = NULL; + set_language (/*getopt*/optarg); + break; + } + case 'm': /* Multiple iterations for finding good asso_values. */ + { + if ((_asso_iterations = atoi (/*getopt*/optarg)) < 0) + { + fprintf (stderr, "asso_iterations value must not be negative, assuming 0\n"); + _asso_iterations = 0; + } + break; + } + case 'n': /* Don't include the length when computing hash function. */ + { + _option_word |= NOLENGTH; + break; + } + case 'N': /* Make generated lookup function name be optarg. */ + { + _function_name = /*getopt*/optarg; + break; + } + case 'o': /* Order input by frequency of key set occurrence. */ + break; /* Not needed any more. */ + case 'O': /* Optimized choice during collision resolution. */ + break; /* Not needed any more. */ + case 'p': /* Generated lookup function a pointer instead of int. */ + break; /* This is now the default. */ + case 'P': /* Optimize for position-independent code. */ + { + _option_word |= SHAREDLIB; + break; + } + case 'Q': /* Sets the name for the string pool. */ + { + _stringpool_name = /*getopt*/optarg; + break; + } + case 'r': /* Utilize randomness to initialize the associated values table. */ + { + _option_word |= RANDOM; + if (_initial_asso_value != 0) + fprintf (stderr, "warning, -r option supersedes -i, disabling -i option and continuing\n"); + break; + } + case 's': /* Range of associated values, determines size of final table. */ + { + float numerator; + float denominator = 1; + bool invalid = false; + char *endptr; + + numerator = strtod (/*getopt*/optarg, &endptr); + if (endptr == /*getopt*/optarg) + invalid = true; + else if (*endptr != '\0') + { + if (*endptr == '/') + { + char *denomptr = endptr + 1; + denominator = strtod (denomptr, &endptr); + if (endptr == denomptr || *endptr != '\0') + invalid = true; + } + else + invalid = true; + } + if (invalid) + { + fprintf (stderr, "Invalid value for option -s.\n"); + short_usage (stderr); + exit (1); + } + _size_multiple = numerator / denominator; + /* Backward compatibility: -3 means 1/3. */ + if (_size_multiple < 0) + _size_multiple = 1 / (-_size_multiple); + /* Catch stupid users. */ + if (_size_multiple == 0) + _size_multiple = 1; + /* Warnings. */ + if (_size_multiple > 50) + fprintf (stderr, "Size multiple %g is excessive, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name); + else if (_size_multiple < 0.01f) + fprintf (stderr, "Size multiple %g is extremely small, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name); + break; + } + case 'S': /* Generate switch statement output, rather than lookup table. */ + { + _option_word |= SWITCH; + _total_switches = atoi (/*getopt*/optarg); + if (_total_switches <= 0) + { + fprintf (stderr, "number of switches %s must be a positive number\n", /*getopt*/optarg); + short_usage (stderr); + exit (1); + } + break; + } + case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */ + { + _option_word |= TYPE; + break; + } + case 'T': /* Don't print structure definition. */ + { + _option_word |= NOTYPE; + break; + } + case 'v': /* Print out the version and quit. */ + fprintf (stdout, "GNU gperf %s\n", version_string); + fprintf (stdout, "Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +", + "1989-1998, 2000-2003"); + fprintf (stdout, "Written by %s and %s.\n", + "Douglas C. Schmidt", "Bruno Haible"); + exit (0); + case 'W': /* Sets the name for the hash table array. */ + { + _wordlist_name = /*getopt*/optarg; + break; + } + case 'Z': /* Set the class name. */ + { + _class_name = /*getopt*/optarg; + break; + } + case '7': /* Assume 7-bit characters. */ + { + _option_word |= SEVENBIT; + break; + } + case CHAR_MAX + 1: /* Set the output file name. */ + { + _output_file_name = /*getopt*/optarg; + break; + } + case CHAR_MAX + 2: /* Case insignificant. */ + { + _option_word |= UPPERLOWER; + break; + } + case CHAR_MAX + 3: /* Use NULL instead of "". */ + { + _option_word |= NULLSTRINGS; + break; + } + default: + short_usage (stderr); + exit (1); + } + + } + + if (/*getopt*/optind < argc) + _input_file_name = argv[/*getopt*/optind++]; + + if (/*getopt*/optind < argc) + { + fprintf (stderr, "Extra trailing arguments to %s.\n", program_name); + short_usage (stderr); + exit (1); + } +} + +/* ------------------------------------------------------------------------- */ + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "options.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/contrib/gperf-3.0.1/src/options.h b/contrib/gperf-3.0.1/src/options.h new file mode 100644 index 0000000000..2507590e45 --- /dev/null +++ b/contrib/gperf-3.0.1/src/options.h @@ -0,0 +1,289 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Handles parsing the Options provided to the user. + + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This module provides a uniform interface to the various options available + to a user of the gperf hash function generator. */ + +#ifndef options_h +#define options_h 1 + +#include +#include "positions.h" + +/* Enumeration of the possible boolean options. */ + +enum Option_Type +{ + /* --- Input file interpretation --- */ + + /* Handle user-defined type structured keyword input. */ + TYPE = 1 << 0, + + /* Ignore case of ASCII characters. */ + UPPERLOWER = 1 << 1, + + /* --- Language for the output code --- */ + + /* Generate K&R C code: no prototypes, no const. */ + KRC = 1 << 2, + + /* Generate C code: no prototypes, but const (user can #define it away). */ + C = 1 << 3, + + /* Generate ISO/ANSI C code: prototypes and const, but no class. */ + ANSIC = 1 << 4, + + /* Generate C++ code: prototypes, const, class, inline, enum. */ + CPLUSPLUS = 1 << 5, + + /* --- Details in the output code --- */ + + /* Assume 7-bit, not 8-bit, characters. */ + SEVENBIT = 1 << 6, + + /* Generate a length table for string comparison. */ + LENTABLE = 1 << 7, + + /* Generate strncmp rather than strcmp. */ + COMP = 1 << 8, + + /* Make the generated tables readonly (const). */ + CONST = 1 << 9, + + /* Use enum for constants. */ + ENUM = 1 << 10, + + /* Generate #include statements. */ + INCLUDE = 1 << 11, + + /* Make the keyword table a global variable. */ + GLOBAL = 1 << 12, + + /* Use NULL strings instead of empty strings for empty table entries. */ + NULLSTRINGS = 1 << 13, + + /* Optimize for position-independent code. */ + SHAREDLIB = 1 << 14, + + /* Generate switch output to save space. */ + SWITCH = 1 << 15, + + /* Don't include user-defined type definition in output -- it's already + defined elsewhere. */ + NOTYPE = 1 << 16, + + /* --- Algorithm employed by gperf --- */ + + /* Use the given key positions. */ + POSITIONS = 1 << 17, + + /* Handle duplicate hash values for keywords. */ + DUP = 1 << 18, + + /* Don't include keyword length in hash computations. */ + NOLENGTH = 1 << 19, + + /* Randomly initialize the associated values table. */ + RANDOM = 1 << 20, + + /* --- Informative output --- */ + + /* Enable debugging (prints diagnostics to stderr). */ + DEBUG = 1 << 21 +}; + +/* Class manager for gperf program Options. */ + +class Options +{ +public: + /* Constructor. */ + Options (); + + /* Destructor. */ + ~Options (); + + /* Parses the options given in the command-line arguments. */ + void parse_options (int argc, char *argv[]); + + /* Prints the given options. */ + void print_options () const; + + /* Accessors. */ + + /* Tests a given boolean option. Returns true if set, false otherwise. */ + bool operator[] (Option_Type option) const; + /* Sets a given boolean option. */ + void set (Option_Type option); + + /* Returns the input file name. */ + const char * get_input_file_name () const; + + /* Returns the output file name. */ + const char * get_output_file_name () const; + + /* Sets the output language, if not already set. */ + void set_language (const char *language); + + /* Returns the jump value. */ + int get_jump () const; + + /* Returns the initial associated character value. */ + int get_initial_asso_value () const; + + /* Returns the number of iterations for finding good asso_values. */ + int get_asso_iterations () const; + + /* Returns the total number of switch statements to generate. */ + int get_total_switches () const; + /* Sets the total number of switch statements, if not already set. */ + void set_total_switches (int total_switches); + + /* Returns the factor by which to multiply the generated table's size. */ + float get_size_multiple () const; + + /* Returns the generated function name. */ + const char * get_function_name () const; + /* Sets the generated function name, if not already set. */ + void set_function_name (const char *name); + + /* Returns the keyword key name. */ + const char * get_slot_name () const; + /* Sets the keyword key name, if not already set. */ + void set_slot_name (const char *name); + + /* Returns the struct initializer suffix. */ + const char * get_initializer_suffix () const; + /* Sets the struct initializer suffix, if not already set. */ + void set_initializer_suffix (const char *initializers); + + /* Returns the generated class name. */ + const char * get_class_name () const; + /* Sets the generated class name, if not already set. */ + void set_class_name (const char *name); + + /* Returns the hash function name. */ + const char * get_hash_name () const; + /* Sets the hash function name, if not already set. */ + void set_hash_name (const char *name); + + /* Returns the hash table array name. */ + const char * get_wordlist_name () const; + /* Sets the hash table array name, if not already set. */ + void set_wordlist_name (const char *name); + + /* Returns the string pool name. */ + const char * get_stringpool_name () const; + /* Sets the string pool name, if not already set. */ + void set_stringpool_name (const char *name); + + /* Returns the string used to delimit keywords from other attributes. */ + const char * get_delimiters () const; + /* Sets the delimiters string, if not already set. */ + void set_delimiters (const char *delimiters); + + /* Returns key positions. */ + const Positions& get_key_positions () const; + +private: + /* Prints program usage to given stream. */ + static void short_usage (FILE * stream); + + /* Prints program usage to given stream. */ + static void long_usage (FILE * stream); + + /* Records count of command-line arguments. */ + int _argument_count; + + /* Stores a pointer to command-line argument vector. */ + char ** _argument_vector; + + /* Holds the boolean options. */ + int _option_word; + + /* Name of input file. */ + char * _input_file_name; + + /* Name of output file. */ + char * _output_file_name; + + /* The output language. */ + const char * _language; + + /* Jump length when trying alternative values. */ + int _jump; + + /* Initial value for asso_values table. */ + int _initial_asso_value; + + /* Number of attempts at finding good asso_values. */ + int _asso_iterations; + + /* Number of switch statements to generate. */ + int _total_switches; + + /* Factor by which to multiply the generated table's size. */ + float _size_multiple; + + /* Names used for generated lookup function. */ + const char * _function_name; + + /* Name used for keyword key. */ + const char * _slot_name; + + /* Suffix for empty struct initializers. */ + const char * _initializer_suffix; + + /* Name used for generated C++ class. */ + const char * _class_name; + + /* Name used for generated hash function. */ + const char * _hash_name; + + /* Name used for hash table array. */ + const char * _wordlist_name; + + /* Name used for the string pool. */ + const char * _stringpool_name; + + /* Separates keywords from other attributes. */ + const char * _delimiters; + + /* Contains user-specified key choices. */ + Positions _key_positions; +}; + +/* Global option coordinator for the entire program. */ +extern Options option; + +#ifdef __OPTIMIZE__ + +#define INLINE inline +#include "options.icc" +#undef INLINE + +#endif + +#endif diff --git a/contrib/gperf-3.0.1/src/options.icc b/contrib/gperf-3.0.1/src/options.icc new file mode 100644 index 0000000000..1d21cc5d99 --- /dev/null +++ b/contrib/gperf-3.0.1/src/options.icc @@ -0,0 +1,150 @@ +/* Inline Functions for options.{h,cc}. + + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* ----------------------------- Class Options ----------------------------- */ + +/* Tests a given boolean option. Returns true if set, false otherwise. */ +INLINE bool +Options::operator[] (Option_Type option) const +{ + return _option_word & option; +} + +/* Sets a given boolean option. */ +INLINE void +Options::set (Option_Type option) +{ + _option_word |= option; +} + +/* Returns the input file name. */ +INLINE const char * +Options::get_input_file_name () const +{ + return _input_file_name; +} + +/* Returns the output file name. */ +INLINE const char * +Options::get_output_file_name () const +{ + return _output_file_name; +} + +/* Returns the jump value. */ +INLINE int +Options::get_jump () const +{ + return _jump; +} + +/* Returns the initial associated character value. */ +INLINE int +Options::get_initial_asso_value () const +{ + return _initial_asso_value; +} + +/* Returns the number of iterations for finding finding good asso_values. */ +INLINE int +Options::get_asso_iterations () const +{ + return _asso_iterations; +} + +/* Returns the total number of switch statements to generate. */ +INLINE int +Options::get_total_switches () const +{ + return _total_switches; +} + +/* Returns the factor by which to multiply the generated table's size. */ +INLINE float +Options::get_size_multiple () const +{ + return _size_multiple; +} + +/* Returns the generated function name. */ +INLINE const char * +Options::get_function_name () const +{ + return _function_name; +} + +/* Returns the keyword key name. */ +INLINE const char * +Options::get_slot_name () const +{ + return _slot_name; +} + +/* Returns the struct initializer suffix. */ +INLINE const char * +Options::get_initializer_suffix () const +{ + return _initializer_suffix; +} + +/* Returns the generated class name. */ +INLINE const char * +Options::get_class_name () const +{ + return _class_name; +} + +/* Returns the hash function name. */ +INLINE const char * +Options::get_hash_name () const +{ + return _hash_name; +} + +/* Returns the hash table array name. */ +INLINE const char * +Options::get_wordlist_name () const +{ + return _wordlist_name; +} + +/* Returns the string pool name. */ +INLINE const char * +Options::get_stringpool_name () const +{ + return _stringpool_name; +} + +/* Returns the string used to delimit keywords from other attributes. */ +INLINE const char * +Options::get_delimiters () const +{ + return _delimiters; +} + +/* Returns key positions. */ +INLINE const Positions& +Options::get_key_positions () const +{ + return _key_positions; +} diff --git a/contrib/gperf-3.0.1/src/output.cc b/contrib/gperf-3.0.1/src/output.cc new file mode 100644 index 0000000000..f6935059f9 --- /dev/null +++ b/contrib/gperf-3.0.1/src/output.cc @@ -0,0 +1,2082 @@ +/* Output routines. + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "output.h" + +#include +#include /* declares strncpy(), strchr() */ +#include /* declares isprint() */ +#include /* defines assert() */ +#include /* defines SCHAR_MAX etc. */ +#include "options.h" +#include "version.h" + +/* The "const " qualifier. */ +static const char *const_always; + +/* The "const " qualifier, for read-only arrays. */ +static const char *const_readonly_array; + +/* The "const " qualifier, for the array type. */ +static const char *const_for_struct; + +/* Returns the smallest unsigned C type capable of holding integers + up to N. */ + +static const char * +smallest_integral_type (int n) +{ + if (n <= UCHAR_MAX) return "unsigned char"; + if (n <= USHRT_MAX) return "unsigned short"; + return "unsigned int"; +} + +/* Returns the smallest signed C type capable of holding integers + from MIN to MAX. */ + +static const char * +smallest_integral_type (int min, int max) +{ + if (option[ANSIC] | option[CPLUSPLUS]) + if (min >= SCHAR_MIN && max <= SCHAR_MAX) return "signed char"; + if (min >= SHRT_MIN && max <= SHRT_MAX) return "short"; + return "int"; +} + +/* ------------------------------------------------------------------------- */ + +/* Constructor. + Note about the keyword list starting at head: + - The list is ordered by increasing _hash_value. This has been achieved + by Search::sort(). + - Duplicates, i.e. keywords with the same _selchars set, are chained + through the _duplicate_link pointer. Only one representative per + duplicate equivalence class remains on the linear keyword list. + - Accidental duplicates, i.e. keywords for which the _asso_values[] search + couldn't achieve different hash values, cannot occur on the linear + keyword list. Search::optimize would catch this mistake. + */ +Output::Output (KeywordExt_List *head, const char *struct_decl, + unsigned int struct_decl_lineno, const char *return_type, + const char *struct_tag, const char *verbatim_declarations, + const char *verbatim_declarations_end, + unsigned int verbatim_declarations_lineno, + const char *verbatim_code, const char *verbatim_code_end, + unsigned int verbatim_code_lineno, bool charset_dependent, + int total_keys, int max_key_len, int min_key_len, + const Positions& positions, const unsigned int *alpha_inc, + int total_duplicates, unsigned int alpha_size, + const int *asso_values) + : _head (head), _struct_decl (struct_decl), + _struct_decl_lineno (struct_decl_lineno), _return_type (return_type), + _struct_tag (struct_tag), + _verbatim_declarations (verbatim_declarations), + _verbatim_declarations_end (verbatim_declarations_end), + _verbatim_declarations_lineno (verbatim_declarations_lineno), + _verbatim_code (verbatim_code), + _verbatim_code_end (verbatim_code_end), + _verbatim_code_lineno (verbatim_code_lineno), + _charset_dependent (charset_dependent), + _total_keys (total_keys), + _max_key_len (max_key_len), _min_key_len (min_key_len), + _key_positions (positions), _alpha_inc (alpha_inc), + _total_duplicates (total_duplicates), _alpha_size (alpha_size), + _asso_values (asso_values) +{ +} + +/* ------------------------------------------------------------------------- */ + +/* Computes the minimum and maximum hash values, and stores them + in _min_hash_value and _max_hash_value. */ + +void +Output::compute_min_max () +{ + /* Since the list is already sorted by hash value all we need to do is + to look at the first and the last element of the list. */ + + _min_hash_value = _head->first()->_hash_value; + + KeywordExt_List *temp; + for (temp = _head; temp->rest(); temp = temp->rest()) + ; + _max_hash_value = temp->first()->_hash_value; +} + +/* ------------------------------------------------------------------------- */ + +/* Returns the number of different hash values. */ + +int +Output::num_hash_values () const +{ + /* Since the list is already sorted by hash value and doesn't contain + duplicates, we can simply count the number of keywords on the list. */ + int count = 0; + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + count++; + return count; +} + +/* -------------------- Output_Constants and subclasses -------------------- */ + +/* This class outputs an enumeration defining some constants. */ + +struct Output_Constants +{ + virtual void output_start () = 0; + virtual void output_item (const char *name, int value) = 0; + virtual void output_end () = 0; + Output_Constants () {} + virtual ~Output_Constants () {} +}; + +/* This class outputs an enumeration in #define syntax. */ + +struct Output_Defines : public Output_Constants +{ + virtual void output_start (); + virtual void output_item (const char *name, int value); + virtual void output_end (); + Output_Defines () {} + virtual ~Output_Defines () {} +}; + +void Output_Defines::output_start () +{ + printf ("\n"); +} + +void Output_Defines::output_item (const char *name, int value) +{ + printf ("#define %s %d\n", name, value); +} + +void Output_Defines::output_end () +{ +} + +/* This class outputs an enumeration using 'enum'. */ + +struct Output_Enum : public Output_Constants +{ + virtual void output_start (); + virtual void output_item (const char *name, int value); + virtual void output_end (); + Output_Enum (const char *indent) + : _indentation (indent) {} + virtual ~Output_Enum () {} +private: + const char *_indentation; + bool _pending_comma; +}; + +void Output_Enum::output_start () +{ + printf ("%senum\n" + "%s {\n", + _indentation, _indentation); + _pending_comma = false; +} + +void Output_Enum::output_item (const char *name, int value) +{ + if (_pending_comma) + printf (",\n"); + printf ("%s %s = %d", _indentation, name, value); + _pending_comma = true; +} + +void Output_Enum::output_end () +{ + if (_pending_comma) + printf ("\n"); + printf ("%s };\n\n", _indentation); +} + +/* Outputs the maximum and minimum hash values etc. */ + +void +Output::output_constants (struct Output_Constants& style) const +{ + style.output_start (); + style.output_item ("TOTAL_KEYWORDS", _total_keys); + style.output_item ("MIN_WORD_LENGTH", _min_key_len); + style.output_item ("MAX_WORD_LENGTH", _max_key_len); + style.output_item ("MIN_HASH_VALUE", _min_hash_value); + style.output_item ("MAX_HASH_VALUE", _max_hash_value); + style.output_end (); +} + +/* ------------------------------------------------------------------------- */ + +/* We use a downcase table because when called repeatedly, the code + gperf_downcase[c] + is faster than + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + */ +#define USE_DOWNCASE_TABLE 1 + +#if USE_DOWNCASE_TABLE + +/* Output gperf's ASCII-downcase table. */ + +static void +output_upperlower_table () +{ + unsigned int c; + + printf ("#ifndef GPERF_DOWNCASE\n" + "#define GPERF_DOWNCASE 1\n" + "static unsigned char gperf_downcase[256] =\n" + " {"); + for (c = 0; c < 256; c++) + { + if ((c % 15) == 0) + printf ("\n "); + printf (" %3d", c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c); + if (c < 255) + printf (","); + } + printf ("\n" + " };\n" + "#endif\n\n"); +} + +#endif + +/* Output gperf's ASCII-case insensitive strcmp replacement. */ + +static void +output_upperlower_strcmp () +{ + printf ("#ifndef GPERF_CASE_STRCMP\n" + "#define GPERF_CASE_STRCMP 1\n" + "static int\n" + "gperf_case_strcmp "); + printf (option[KRC] ? + "(s1, s2)\n" + " register char *s1;\n" + " register char *s2;\n" : + option[C] ? + "(s1, s2)\n" + " register const char *s1;\n" + " register const char *s2;\n" : + option[ANSIC] | option[CPLUSPLUS] ? + "(register const char *s1, register const char *s2)\n" : + ""); + #if USE_DOWNCASE_TABLE + printf ("{\n" + " for (;;)\n" + " {\n" + " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n" + " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n" + " if (c1 != 0 && c1 == c2)\n" + " continue;\n" + " return (int)c1 - (int)c2;\n" + " }\n" + "}\n"); + #else + printf ("{\n" + " for (;;)\n" + " {\n" + " unsigned char c1 = *s1++;\n" + " unsigned char c2 = *s2++;\n" + " if (c1 >= 'A' && c1 <= 'Z')\n" + " c1 += 'a' - 'A';\n" + " if (c2 >= 'A' && c2 <= 'Z')\n" + " c2 += 'a' - 'A';\n" + " if (c1 != 0 && c1 == c2)\n" + " continue;\n" + " return (int)c1 - (int)c2;\n" + " }\n" + "}\n"); + #endif + printf ("#endif\n\n"); +} + +/* Output gperf's ASCII-case insensitive strncmp replacement. */ + +static void +output_upperlower_strncmp () +{ + printf ("#ifndef GPERF_CASE_STRNCMP\n" + "#define GPERF_CASE_STRNCMP 1\n" + "static int\n" + "gperf_case_strncmp "); + printf (option[KRC] ? + "(s1, s2, n)\n" + " register char *s1;\n" + " register char *s2;\n" + " register unsigned int n;\n" : + option[C] ? + "(s1, s2, n)\n" + " register const char *s1;\n" + " register const char *s2;\n" + " register unsigned int n;\n" : + option[ANSIC] | option[CPLUSPLUS] ? + "(register const char *s1, register const char *s2, register unsigned int n)\n" : + ""); + #if USE_DOWNCASE_TABLE + printf ("{\n" + " for (; n > 0;)\n" + " {\n" + " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n" + " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n" + " if (c1 != 0 && c1 == c2)\n" + " {\n" + " n--;\n" + " continue;\n" + " }\n" + " return (int)c1 - (int)c2;\n" + " }\n" + " return 0;\n" + "}\n"); + #else + printf ("{\n" + " for (; n > 0;)\n" + " {\n" + " unsigned char c1 = *s1++;\n" + " unsigned char c2 = *s2++;\n" + " if (c1 >= 'A' && c1 <= 'Z')\n" + " c1 += 'a' - 'A';\n" + " if (c2 >= 'A' && c2 <= 'Z')\n" + " c2 += 'a' - 'A';\n" + " if (c1 != 0 && c1 == c2)\n" + " {\n" + " n--;\n" + " continue;\n" + " }\n" + " return (int)c1 - (int)c2;\n" + " }\n" + " return 0;\n" + "}\n"); + #endif + printf ("#endif\n\n"); +} + +/* Output gperf's ASCII-case insensitive memcmp replacement. */ + +static void +output_upperlower_memcmp () +{ + printf ("#ifndef GPERF_CASE_MEMCMP\n" + "#define GPERF_CASE_MEMCMP 1\n" + "static int\n" + "gperf_case_memcmp "); + printf (option[KRC] ? + "(s1, s2, n)\n" + " register char *s1;\n" + " register char *s2;\n" + " register unsigned int n;\n" : + option[C] ? + "(s1, s2, n)\n" + " register const char *s1;\n" + " register const char *s2;\n" + " register unsigned int n;\n" : + option[ANSIC] | option[CPLUSPLUS] ? + "(register const char *s1, register const char *s2, register unsigned int n)\n" : + ""); + #if USE_DOWNCASE_TABLE + printf ("{\n" + " for (; n > 0;)\n" + " {\n" + " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n" + " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n" + " if (c1 == c2)\n" + " {\n" + " n--;\n" + " continue;\n" + " }\n" + " return (int)c1 - (int)c2;\n" + " }\n" + " return 0;\n" + "}\n"); + #else + printf ("{\n" + " for (; n > 0;)\n" + " {\n" + " unsigned char c1 = *s1++;\n" + " unsigned char c2 = *s2++;\n" + " if (c1 >= 'A' && c1 <= 'Z')\n" + " c1 += 'a' - 'A';\n" + " if (c2 >= 'A' && c2 <= 'Z')\n" + " c2 += 'a' - 'A';\n" + " if (c1 == c2)\n" + " {\n" + " n--;\n" + " continue;\n" + " }\n" + " return (int)c1 - (int)c2;\n" + " }\n" + " return 0;\n" + "}\n"); + #endif + printf ("#endif\n\n"); +} + +/* ------------------------------------------------------------------------- */ + +/* Outputs a keyword, as a string: enclosed in double quotes, escaping + backslashes, double quote and unprintable characters. */ + +static void +output_string (const char *key, int len) +{ + putchar ('"'); + for (; len > 0; len--) + { + unsigned char c = static_cast(*key++); + if (isprint (c)) + { + if (c == '"' || c == '\\') + putchar ('\\'); + putchar (c); + } + else + { + /* Use octal escapes, not hexadecimal escapes, because some old + C compilers didn't understand hexadecimal escapes, and because + hexadecimal escapes are not limited to 2 digits, thus needing + special care if the following character happens to be a digit. */ + putchar ('\\'); + putchar ('0' + ((c >> 6) & 7)); + putchar ('0' + ((c >> 3) & 7)); + putchar ('0' + (c & 7)); + } + } + putchar ('"'); +} + +/* ------------------------------------------------------------------------- */ + +/* Outputs a type and a const specifier (i.e. "const " or ""). + The output is terminated with a space. */ + +static void +output_const_type (const char *const_string, const char *type_string) +{ + if (type_string[strlen(type_string)-1] == '*') + /* For pointer types, put the 'const' after the type. */ + printf ("%s %s", type_string, const_string); + else + /* For scalar or struct types, put the 'const' before the type. */ + printf ("%s%s ", const_string, type_string); +} + +/* ----------------------- Output_Expr and subclasses ----------------------- */ + +/* This class outputs a general expression. */ + +struct Output_Expr +{ + virtual void output_expr () const = 0; + Output_Expr () {} + virtual ~Output_Expr () {} +}; + +/* This class outputs an expression formed by a single string. */ + +struct Output_Expr1 : public Output_Expr +{ + virtual void output_expr () const; + Output_Expr1 (const char *piece1) : _p1 (piece1) {} + virtual ~Output_Expr1 () {} +private: + const char *_p1; +}; + +void Output_Expr1::output_expr () const +{ + printf ("%s", _p1); +} + +#if 0 /* unused */ + +/* This class outputs an expression formed by the concatenation of two + strings. */ + +struct Output_Expr2 : public Output_Expr +{ + virtual void output_expr () const; + Output_Expr2 (const char *piece1, const char *piece2) + : _p1 (piece1), _p2 (piece2) {} + virtual ~Output_Expr2 () {} +private: + const char *_p1; + const char *_p2; +}; + +void Output_Expr2::output_expr () const +{ + printf ("%s%s", _p1, _p2); +} + +#endif + +/* --------------------- Output_Compare and subclasses --------------------- */ + +/* This class outputs a comparison expression. */ + +struct Output_Compare +{ + /* Outputs the comparison expression. + expr1 outputs a simple expression of type 'const char *' referring to + the string being looked up. expr2 outputs a simple expression of type + 'const char *' referring to the constant string stored in the gperf + generated hash table. */ + virtual void output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const = 0; + /* Outputs the comparison expression for the first byte. + Returns true if the this comparison is complete. */ + bool output_firstchar_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const; + Output_Compare () {} + virtual ~Output_Compare () {} +}; + +bool Output_Compare::output_firstchar_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const +{ + /* First, we emit a comparison of the first byte of the two strings. + This catches most cases where the string being looked up is not in the + hash table but happens to have the same hash code as an element of the + hash table. */ + if (option[UPPERLOWER]) + { + /* Incomplete comparison, just for speedup. */ + printf ("(((unsigned char)*"); + expr1.output_expr (); + printf (" ^ (unsigned char)*"); + expr2.output_expr (); + printf (") & ~32) == 0"); + return false; + } + else + { + /* Complete comparison. */ + printf ("*"); + expr1.output_expr (); + printf (" == *"); + expr2.output_expr (); + return true; + } +} + +/* This class outputs a comparison using strcmp. */ + +struct Output_Compare_Strcmp : public Output_Compare +{ + virtual void output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const; + Output_Compare_Strcmp () {} + virtual ~Output_Compare_Strcmp () {} +}; + +void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const +{ + bool firstchar_done = output_firstchar_comparison (expr1, expr2); + printf (" && !"); + if (option[UPPERLOWER]) + printf ("gperf_case_"); + printf ("strcmp ("); + if (firstchar_done) + { + expr1.output_expr (); + printf (" + 1, "); + expr2.output_expr (); + printf (" + 1"); + } + else + { + expr1.output_expr (); + printf (", "); + expr2.output_expr (); + } + printf (")"); +} + +/* This class outputs a comparison using strncmp. + Note that the length of expr1 will be available through the local variable + 'len'. */ + +struct Output_Compare_Strncmp : public Output_Compare +{ + virtual void output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const; + Output_Compare_Strncmp () {} + virtual ~Output_Compare_Strncmp () {} +}; + +void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const +{ + bool firstchar_done = output_firstchar_comparison (expr1, expr2); + printf (" && !"); + if (option[UPPERLOWER]) + printf ("gperf_case_"); + printf ("strncmp ("); + if (firstchar_done) + { + expr1.output_expr (); + printf (" + 1, "); + expr2.output_expr (); + printf (" + 1, len - 1"); + } + else + { + expr1.output_expr (); + printf (", "); + expr2.output_expr (); + printf (", len"); + } + printf (") && "); + expr2.output_expr (); + printf ("[len] == '\\0'"); +} + +/* This class outputs a comparison using memcmp. + Note that the length of expr1 (available through the local variable 'len') + must be verified to be equal to the length of expr2 prior to this + comparison. */ + +struct Output_Compare_Memcmp : public Output_Compare +{ + virtual void output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const; + Output_Compare_Memcmp () {} + virtual ~Output_Compare_Memcmp () {} +}; + +void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const +{ + bool firstchar_done = output_firstchar_comparison (expr1, expr2); + printf (" && !"); + if (option[UPPERLOWER]) + printf ("gperf_case_"); + printf ("memcmp ("); + if (firstchar_done) + { + expr1.output_expr (); + printf (" + 1, "); + expr2.output_expr (); + printf (" + 1, len - 1"); + } + else + { + expr1.output_expr (); + printf (", "); + expr2.output_expr (); + printf (", len"); + } + printf (")"); +} + +/* ------------------------------------------------------------------------- */ + +/* Generates a C expression for an asso_values[] reference. */ + +void +Output::output_asso_values_ref (int pos) const +{ + printf ("asso_values["); + /* Always cast to unsigned char. This is necessary when the alpha_inc + is nonzero, and also avoids a gcc warning "subscript has type 'char'". */ + printf ("(unsigned char)"); + if (pos == Positions::LASTCHAR) + printf ("str[len - 1]"); + else + { + printf ("str[%d]", pos); + if (_alpha_inc[pos]) + printf ("+%u", _alpha_inc[pos]); + } + printf ("]"); +} + +/* Generates C code for the hash function that returns the + proper encoding for each keyword. + The hash function has the signature + unsigned int (const char *str, unsigned int len). */ + +void +Output::output_hash_function () const +{ + /* Output the function's head. */ + if (option[CPLUSPLUS]) + printf ("inline "); + else if (option[KRC] | option[C] | option[ANSIC]) + printf ("#ifdef __GNUC__\n" + "__inline\n" + "#else\n" + "#ifdef __cplusplus\n" + "inline\n" + "#endif\n" + "#endif\n"); + + if (/* The function does not use the 'str' argument? */ + _key_positions.get_size() == 0 + || /* The function uses 'str', but not the 'len' argument? */ + (option[NOLENGTH] + && _key_positions[0] < _min_key_len + && _key_positions[_key_positions.get_size() - 1] != Positions::LASTCHAR)) + /* Pacify lint. */ + printf ("/*ARGSUSED*/\n"); + + if (option[KRC] | option[C] | option[ANSIC]) + printf ("static "); + printf ("unsigned int\n"); + if (option[CPLUSPLUS]) + printf ("%s::", option.get_class_name ()); + printf ("%s ", option.get_hash_name ()); + printf (option[KRC] ? + "(str, len)\n" + " register char *str;\n" + " register unsigned int len;\n" : + option[C] ? + "(str, len)\n" + " register const char *str;\n" + " register unsigned int len;\n" : + option[ANSIC] | option[CPLUSPLUS] ? + "(register const char *str, register unsigned int len)\n" : + ""); + + /* Note that when the hash function is called, it has already been verified + that min_key_len <= len <= max_key_len. */ + + /* Output the function's body. */ + printf ("{\n"); + + /* First the asso_values array. */ + if (_key_positions.get_size() > 0) + { + printf (" static %s%s asso_values[] =\n" + " {", + const_readonly_array, + smallest_integral_type (_max_hash_value + 1)); + + const int columns = 10; + + /* Calculate maximum number of digits required for MAX_HASH_VALUE. */ + int field_width = 2; + for (int trunc = _max_hash_value; (trunc /= 10) > 0;) + field_width++; + + for (unsigned int count = 0; count < _alpha_size; count++) + { + if (count > 0) + printf (","); + if ((count % columns) == 0) + printf ("\n "); + printf ("%*d", field_width, _asso_values[count]); + } + + printf ("\n" + " };\n"); + } + + if (_key_positions.get_size() == 0) + { + /* Trivial case: No key positions at all. */ + printf (" return %s;\n", + option[NOLENGTH] ? "0" : "len"); + } + else + { + /* Iterate through the key positions. Remember that Positions::sort() + has sorted them in decreasing order, with Positions::LASTCHAR coming + last. */ + PositionIterator iter = _key_positions.iterator(_max_key_len); + int key_pos; + + /* Get the highest key position. */ + key_pos = iter.next (); + + if (key_pos == Positions::LASTCHAR || key_pos < _min_key_len) + { + /* We can perform additional optimizations here: + Write it out as a single expression. Note that the values + are added as 'int's even though the asso_values array may + contain 'unsigned char's or 'unsigned short's. */ + + printf (" return %s", + option[NOLENGTH] ? "" : "len + "); + + if (_key_positions.get_size() == 2 + && _key_positions[0] == 0 + && _key_positions[1] == Positions::LASTCHAR) + /* Optimize special case of "-k 1,$". */ + { + output_asso_values_ref (Positions::LASTCHAR); + printf (" + "); + output_asso_values_ref (0); + } + else + { + for (; key_pos != Positions::LASTCHAR; ) + { + output_asso_values_ref (key_pos); + if ((key_pos = iter.next ()) != PositionIterator::EOS) + printf (" + "); + else + break; + } + + if (key_pos == Positions::LASTCHAR) + output_asso_values_ref (Positions::LASTCHAR); + } + + printf (";\n"); + } + else + { + /* We've got to use the correct, but brute force, technique. */ + printf (" register int hval = %s;\n\n" + " switch (%s)\n" + " {\n" + " default:\n", + option[NOLENGTH] ? "0" : "len", + option[NOLENGTH] ? "len" : "hval"); + + while (key_pos != Positions::LASTCHAR && key_pos >= _max_key_len) + if ((key_pos = iter.next ()) == PositionIterator::EOS) + break; + + if (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR) + { + int i = key_pos; + do + { + if (i > key_pos) + printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */ + for ( ; i > key_pos; i--) + printf (" case %d:\n", i); + + printf (" hval += "); + output_asso_values_ref (key_pos); + printf (";\n"); + + key_pos = iter.next (); + } + while (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR); + + if (i >= _min_key_len) + printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */ + for ( ; i >= _min_key_len; i--) + printf (" case %d:\n", i); + } + + printf (" break;\n" + " }\n" + " return hval"); + if (key_pos == Positions::LASTCHAR) + { + printf (" + "); + output_asso_values_ref (Positions::LASTCHAR); + } + printf (";\n"); + } + } + printf ("}\n\n"); +} + +/* ------------------------------------------------------------------------- */ + +/* Prints out a table of keyword lengths, for use with the + comparison code in generated function 'in_word_set'. + Only called if option[LENTABLE]. */ + +void +Output::output_keylength_table () const +{ + const int columns = 14; + const char * const indent = option[GLOBAL] ? "" : " "; + + printf ("%sstatic %s%s lengthtable[] =\n%s {", + indent, const_readonly_array, + smallest_integral_type (_max_key_len), + indent); + + /* Generate an array of lengths, similar to output_keyword_table. */ + int index; + int column; + KeywordExt_List *temp; + + column = 0; + for (temp = _head, index = 0; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + /* If generating a switch statement, and there is no user defined type, + we generate non-duplicates directly in the code. Only duplicates go + into the table. */ + if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) + continue; + + if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP]) + { + /* Some blank entries. */ + for ( ; index < keyword->_hash_value; index++) + { + if (index > 0) + printf (","); + if ((column++ % columns) == 0) + printf ("\n%s ", indent); + printf ("%3d", 0); + } + } + + if (index > 0) + printf (","); + if ((column++ % columns) == 0) + printf("\n%s ", indent); + printf ("%3d", keyword->_allchars_length); + index++; + + /* Deal with duplicates specially. */ + if (keyword->_duplicate_link) // implies option[DUP] + for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) + { + printf (","); + if ((column++ % columns) == 0) + printf("\n%s ", indent); + printf ("%3d", links->_allchars_length); + index++; + } + } + + printf ("\n%s };\n", indent); + if (option[GLOBAL]) + printf ("\n"); +} + +/* ------------------------------------------------------------------------- */ + +/* Prints out the string pool, containing the strings of the keyword table. + Only called if option[SHAREDLIB]. */ + +void +Output::output_string_pool () const +{ + const char * const indent = option[TYPE] || option[GLOBAL] ? "" : " "; + int index; + KeywordExt_List *temp; + + printf ("%sstruct %s_t\n" + "%s {\n", + indent, option.get_stringpool_name (), indent); + for (temp = _head, index = 0; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + /* If generating a switch statement, and there is no user defined type, + we generate non-duplicates directly in the code. Only duplicates go + into the table. */ + if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) + continue; + + if (!option[SWITCH] && !option[DUP]) + index = keyword->_hash_value; + + printf ("%s char %s_str%d[sizeof(", + indent, option.get_stringpool_name (), index); + output_string (keyword->_allchars, keyword->_allchars_length); + printf (")];\n"); + + /* Deal with duplicates specially. */ + if (keyword->_duplicate_link) // implies option[DUP] + for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) + if (!(links->_allchars_length == keyword->_allchars_length + && memcmp (links->_allchars, keyword->_allchars, + keyword->_allchars_length) == 0)) + { + index++; + printf ("%s char %s_str%d[sizeof(", + indent, option.get_stringpool_name (), index); + output_string (links->_allchars, links->_allchars_length); + printf (")];\n"); + } + + index++; + } + printf ("%s };\n", + indent); + + printf ("%sstatic %sstruct %s_t %s_contents =\n" + "%s {\n", + indent, const_readonly_array, option.get_stringpool_name (), + option.get_stringpool_name (), indent); + for (temp = _head, index = 0; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + /* If generating a switch statement, and there is no user defined type, + we generate non-duplicates directly in the code. Only duplicates go + into the table. */ + if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) + continue; + + if (index > 0) + printf (",\n"); + + if (!option[SWITCH] && !option[DUP]) + index = keyword->_hash_value; + + printf ("%s ", + indent); + output_string (keyword->_allchars, keyword->_allchars_length); + + /* Deal with duplicates specially. */ + if (keyword->_duplicate_link) // implies option[DUP] + for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) + if (!(links->_allchars_length == keyword->_allchars_length + && memcmp (links->_allchars, keyword->_allchars, + keyword->_allchars_length) == 0)) + { + index++; + printf (",\n"); + printf ("%s ", + indent); + output_string (links->_allchars, links->_allchars_length); + } + + index++; + } + if (index > 0) + printf ("\n"); + printf ("%s };\n", + indent); + printf ("%s#define %s ((%schar *) &%s_contents)\n", + indent, option.get_stringpool_name (), const_always, + option.get_stringpool_name ()); + if (option[GLOBAL]) + printf ("\n"); +} + +/* ------------------------------------------------------------------------- */ + +static void +output_keyword_entry (KeywordExt *temp, int stringpool_index, const char *indent) +{ + if (option[TYPE] && option.get_input_file_name ()) + printf ("#line %u \"%s\"\n", + temp->_lineno, option.get_input_file_name ()); + printf ("%s ", indent); + if (option[TYPE]) + printf ("{"); + if (option[SHAREDLIB]) + printf ("(int)(long)&((struct %s_t *)0)->%s_str%d", + option.get_stringpool_name (), option.get_stringpool_name (), + stringpool_index); + else + output_string (temp->_allchars, temp->_allchars_length); + if (option[TYPE]) + { + if (strlen (temp->_rest) > 0) + printf (",%s", temp->_rest); + printf ("}"); + } + if (option[DEBUG]) + printf (" /* hash value = %d, index = %d */", + temp->_hash_value, temp->_final_index); +} + +static void +output_keyword_blank_entries (int count, const char *indent) +{ + int columns; + if (option[TYPE]) + { + columns = 58 / (4 + (option[SHAREDLIB] ? 2 : option[NULLSTRINGS] ? 8 : 2) + + strlen (option.get_initializer_suffix())); + if (columns == 0) + columns = 1; + } + else + { + columns = (option[SHAREDLIB] ? 9 : option[NULLSTRINGS] ? 4 : 9); + } + int column = 0; + for (int i = 0; i < count; i++) + { + if ((column % columns) == 0) + { + if (i > 0) + printf (",\n"); + printf ("%s ", indent); + } + else + { + if (i > 0) + printf (", "); + } + if (option[TYPE]) + printf ("{"); + if (option[SHAREDLIB]) + printf ("-1"); + else + { + if (option[NULLSTRINGS]) + printf ("(char*)0"); + else + printf ("\"\""); + } + if (option[TYPE]) + printf ("%s}", option.get_initializer_suffix()); + column++; + } +} + +/* Prints out the array containing the keywords for the hash function. */ + +void +Output::output_keyword_table () const +{ + const char *indent = option[GLOBAL] ? "" : " "; + int index; + KeywordExt_List *temp; + + printf ("%sstatic ", + indent); + output_const_type (const_readonly_array, _wordlist_eltype); + printf ("%s[] =\n" + "%s {\n", + option.get_wordlist_name (), + indent); + + /* Generate an array of reserved words at appropriate locations. */ + + for (temp = _head, index = 0; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + /* If generating a switch statement, and there is no user defined type, + we generate non-duplicates directly in the code. Only duplicates go + into the table. */ + if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) + continue; + + if (index > 0) + printf (",\n"); + + if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP]) + { + /* Some blank entries. */ + output_keyword_blank_entries (keyword->_hash_value - index, indent); + printf (",\n"); + index = keyword->_hash_value; + } + + keyword->_final_index = index; + + output_keyword_entry (keyword, index, indent); + + /* Deal with duplicates specially. */ + if (keyword->_duplicate_link) // implies option[DUP] + for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) + { + links->_final_index = ++index; + printf (",\n"); + int stringpool_index = + (links->_allchars_length == keyword->_allchars_length + && memcmp (links->_allchars, keyword->_allchars, + keyword->_allchars_length) == 0 + ? keyword->_final_index + : links->_final_index); + output_keyword_entry (links, stringpool_index, indent); + } + + index++; + } + if (index > 0) + printf ("\n"); + + printf ("%s };\n\n", indent); +} + +/* ------------------------------------------------------------------------- */ + +/* Generates the large, sparse table that maps hash values into + the smaller, contiguous range of the keyword table. */ + +void +Output::output_lookup_array () const +{ + if (option[DUP]) + { + const int DEFAULT_VALUE = -1; + + /* Because of the way output_keyword_table works, every duplicate set is + stored contiguously in the wordlist array. */ + struct duplicate_entry + { + int hash_value; /* Hash value for this particular duplicate set. */ + int index; /* Index into the main keyword storage array. */ + int count; /* Number of consecutive duplicates at this index. */ + }; + + duplicate_entry *duplicates = new duplicate_entry[_total_duplicates]; + int *lookup_array = new int[_max_hash_value + 1 + 2*_total_duplicates]; + int lookup_array_size = _max_hash_value + 1; + duplicate_entry *dup_ptr = &duplicates[0]; + int *lookup_ptr = &lookup_array[_max_hash_value + 1 + 2*_total_duplicates]; + + while (lookup_ptr > lookup_array) + *--lookup_ptr = DEFAULT_VALUE; + + /* Now dup_ptr = &duplicates[0] and lookup_ptr = &lookup_array[0]. */ + + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + int hash_value = temp->first()->_hash_value; + lookup_array[hash_value] = temp->first()->_final_index; + if (option[DEBUG]) + fprintf (stderr, "keyword = %.*s, index = %d\n", + temp->first()->_allchars_length, temp->first()->_allchars, temp->first()->_final_index); + if (temp->first()->_duplicate_link) + { + /* Start a duplicate entry. */ + dup_ptr->hash_value = hash_value; + dup_ptr->index = temp->first()->_final_index; + dup_ptr->count = 1; + + for (KeywordExt *ptr = temp->first()->_duplicate_link; ptr; ptr = ptr->_duplicate_link) + { + dup_ptr->count++; + if (option[DEBUG]) + fprintf (stderr, + "static linked keyword = %.*s, index = %d\n", + ptr->_allchars_length, ptr->_allchars, ptr->_final_index); + } + assert (dup_ptr->count >= 2); + dup_ptr++; + } + } + + while (dup_ptr > duplicates) + { + dup_ptr--; + + if (option[DEBUG]) + fprintf (stderr, + "dup_ptr[%d]: hash_value = %d, index = %d, count = %d\n", + dup_ptr - duplicates, + dup_ptr->hash_value, dup_ptr->index, dup_ptr->count); + + int i; + /* Start searching for available space towards the right part + of the lookup array. */ + for (i = dup_ptr->hash_value; i < lookup_array_size-1; i++) + if (lookup_array[i] == DEFAULT_VALUE + && lookup_array[i + 1] == DEFAULT_VALUE) + goto found_i; + /* If we didn't find it to the right look to the left instead... */ + for (i = dup_ptr->hash_value-1; i >= 0; i--) + if (lookup_array[i] == DEFAULT_VALUE + && lookup_array[i + 1] == DEFAULT_VALUE) + goto found_i; + /* Append to the end of lookup_array. */ + i = lookup_array_size; + lookup_array_size += 2; + found_i: + /* Put in an indirection from dup_ptr->_hash_value to i. + At i and i+1 store dup_ptr->_final_index and dup_ptr->count. */ + assert (lookup_array[dup_ptr->hash_value] == dup_ptr->index); + lookup_array[dup_ptr->hash_value] = - 1 - _total_keys - i; + lookup_array[i] = - _total_keys + dup_ptr->index; + lookup_array[i + 1] = - dup_ptr->count; + /* All these three values are <= -2, distinct from DEFAULT_VALUE. */ + } + + /* The values of the lookup array are now known. */ + + int min = INT_MAX; + int max = INT_MIN; + lookup_ptr = lookup_array + lookup_array_size; + while (lookup_ptr > lookup_array) + { + int val = *--lookup_ptr; + if (min > val) + min = val; + if (max < val) + max = val; + } + + const char *indent = option[GLOBAL] ? "" : " "; + printf ("%sstatic %s%s lookup[] =\n" + "%s {", + indent, const_readonly_array, smallest_integral_type (min, max), + indent); + + int field_width; + /* Calculate maximum number of digits required for MIN..MAX. */ + { + field_width = 2; + for (int trunc = max; (trunc /= 10) > 0;) + field_width++; + } + if (min < 0) + { + int neg_field_width = 2; + for (int trunc = -min; (trunc /= 10) > 0;) + neg_field_width++; + neg_field_width++; /* account for the minus sign */ + if (field_width < neg_field_width) + field_width = neg_field_width; + } + + const int columns = 42 / field_width; + int column; + + column = 0; + for (int i = 0; i < lookup_array_size; i++) + { + if (i > 0) + printf (","); + if ((column++ % columns) == 0) + printf("\n%s ", indent); + printf ("%*d", field_width, lookup_array[i]); + } + printf ("\n%s };\n\n", indent); + + delete[] duplicates; + delete[] lookup_array; + } +} + +/* ------------------------------------------------------------------------- */ + +/* Generate all pools needed for the lookup function. */ + +void +Output::output_lookup_pools () const +{ + if (option[SWITCH]) + { + if (option[TYPE] || (option[DUP] && _total_duplicates > 0)) + output_string_pool (); + } + else + { + output_string_pool (); + } +} + +/* Generate all the tables needed for the lookup function. */ + +void +Output::output_lookup_tables () const +{ + if (option[SWITCH]) + { + /* Use the switch in place of lookup table. */ + if (option[LENTABLE] && (option[DUP] && _total_duplicates > 0)) + output_keylength_table (); + if (option[TYPE] || (option[DUP] && _total_duplicates > 0)) + output_keyword_table (); + } + else + { + /* Use the lookup table, in place of switch. */ + if (option[LENTABLE]) + output_keylength_table (); + output_keyword_table (); + output_lookup_array (); + } +} + +/* ------------------------------------------------------------------------- */ + +/* Output a single switch case (including duplicates). Advance list. */ + +static KeywordExt_List * +output_switch_case (KeywordExt_List *list, int indent, int *jumps_away) +{ + if (option[DEBUG]) + printf ("%*s/* hash value = %4d, keyword = \"%.*s\" */\n", + indent, "", list->first()->_hash_value, list->first()->_allchars_length, list->first()->_allchars); + + if (option[DUP] && list->first()->_duplicate_link) + { + if (option[LENTABLE]) + printf ("%*slengthptr = &lengthtable[%d];\n", + indent, "", list->first()->_final_index); + printf ("%*swordptr = &%s[%d];\n", + indent, "", option.get_wordlist_name (), list->first()->_final_index); + + int count = 0; + for (KeywordExt *links = list->first(); links; links = links->_duplicate_link) + count++; + + printf ("%*swordendptr = wordptr + %d;\n" + "%*sgoto multicompare;\n", + indent, "", count, + indent, ""); + *jumps_away = 1; + } + else + { + if (option[LENTABLE]) + { + printf ("%*sif (len == %d)\n" + "%*s {\n", + indent, "", list->first()->_allchars_length, + indent, ""); + indent += 4; + } + printf ("%*sresword = ", + indent, ""); + if (option[TYPE]) + printf ("&%s[%d]", option.get_wordlist_name (), list->first()->_final_index); + else + output_string (list->first()->_allchars, list->first()->_allchars_length); + printf (";\n"); + printf ("%*sgoto compare;\n", + indent, ""); + if (option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", + indent, ""); + } + else + *jumps_away = 1; + } + + return list->rest(); +} + +/* Output a total of size cases, grouped into num_switches switch statements, + where 0 < num_switches <= size. */ + +static void +output_switches (KeywordExt_List *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent) +{ + if (option[DEBUG]) + printf ("%*s/* know %d <= key <= %d, contains %d cases */\n", + indent, "", min_hash_value, max_hash_value, size); + + if (num_switches > 1) + { + int part1 = num_switches / 2; + int part2 = num_switches - part1; + int size1 = static_cast(static_cast(size) / static_cast(num_switches) * static_cast(part1) + 0.5); + int size2 = size - size1; + + KeywordExt_List *temp = list; + for (int count = size1; count > 0; count--) + temp = temp->rest(); + + printf ("%*sif (key < %d)\n" + "%*s {\n", + indent, "", temp->first()->_hash_value, + indent, ""); + + output_switches (list, part1, size1, min_hash_value, temp->first()->_hash_value-1, indent+4); + + printf ("%*s }\n" + "%*selse\n" + "%*s {\n", + indent, "", indent, "", indent, ""); + + output_switches (temp, part2, size2, temp->first()->_hash_value, max_hash_value, indent+4); + + printf ("%*s }\n", + indent, ""); + } + else + { + /* Output a single switch. */ + int lowest_case_value = list->first()->_hash_value; + if (size == 1) + { + int jumps_away = 0; + assert (min_hash_value <= lowest_case_value); + assert (lowest_case_value <= max_hash_value); + if (min_hash_value == max_hash_value) + output_switch_case (list, indent, &jumps_away); + else + { + printf ("%*sif (key == %d)\n" + "%*s {\n", + indent, "", lowest_case_value, + indent, ""); + output_switch_case (list, indent+4, &jumps_away); + printf ("%*s }\n", + indent, ""); + } + } + else + { + if (lowest_case_value == 0) + printf ("%*sswitch (key)\n", indent, ""); + else + printf ("%*sswitch (key - %d)\n", indent, "", lowest_case_value); + printf ("%*s {\n", + indent, ""); + for (; size > 0; size--) + { + int jumps_away = 0; + printf ("%*s case %d:\n", + indent, "", list->first()->_hash_value - lowest_case_value); + list = output_switch_case (list, indent+6, &jumps_away); + if (!jumps_away) + printf ("%*s break;\n", + indent, ""); + } + printf ("%*s }\n", + indent, ""); + } + } +} + +/* Generates C code to perform the keyword lookup. */ + +void +Output::output_lookup_function_body (const Output_Compare& comparison) const +{ + printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n" + " {\n" + " register int key = %s (str, len);\n\n", + option.get_hash_name ()); + + if (option[SWITCH]) + { + int switch_size = num_hash_values (); + int num_switches = option.get_total_switches (); + if (num_switches > switch_size) + num_switches = switch_size; + + printf (" if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n" + " {\n"); + if (option[DUP] && _total_duplicates > 0) + { + if (option[LENTABLE]) + printf (" register %s%s *lengthptr;\n", + const_always, smallest_integral_type (_max_key_len)); + printf (" register "); + output_const_type (const_readonly_array, _wordlist_eltype); + printf ("*wordptr;\n"); + printf (" register "); + output_const_type (const_readonly_array, _wordlist_eltype); + printf ("*wordendptr;\n"); + } + if (option[TYPE]) + { + printf (" register "); + output_const_type (const_readonly_array, _struct_tag); + printf ("*resword;\n\n"); + } + else + printf (" register %sresword;\n\n", + _struct_tag); + + output_switches (_head, num_switches, switch_size, _min_hash_value, _max_hash_value, 10); + + printf (" return 0;\n"); + if (option[DUP] && _total_duplicates > 0) + { + int indent = 8; + printf ("%*smulticompare:\n" + "%*s while (wordptr < wordendptr)\n" + "%*s {\n", + indent, "", indent, "", indent, ""); + if (option[LENTABLE]) + { + printf ("%*s if (len == *lengthptr)\n" + "%*s {\n", + indent, "", indent, ""); + indent += 4; + } + printf ("%*s register %schar *s = ", + indent, "", const_always); + if (option[TYPE]) + printf ("wordptr->%s", option.get_slot_name ()); + else + printf ("*wordptr"); + if (option[SHAREDLIB]) + printf (" + %s", + option.get_stringpool_name ()); + printf (";\n\n" + "%*s if (", + indent, ""); + comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); + printf (")\n" + "%*s return %s;\n", + indent, "", + option[TYPE] ? "wordptr" : "s"); + if (option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", + indent, ""); + } + if (option[LENTABLE]) + printf ("%*s lengthptr++;\n", + indent, ""); + printf ("%*s wordptr++;\n" + "%*s }\n" + "%*s return 0;\n", + indent, "", indent, "", indent, ""); + } + printf (" compare:\n"); + if (option[TYPE]) + { + printf (" {\n" + " register %schar *s = resword->%s", + const_always, option.get_slot_name ()); + if (option[SHAREDLIB]) + printf (" + %s", + option.get_stringpool_name ()); + printf (";\n\n" + " if ("); + comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); + printf (")\n" + " return resword;\n" + " }\n"); + } + else + { + printf (" if ("); + comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("resword")); + printf (")\n" + " return resword;\n"); + } + printf (" }\n"); + } + else + { + printf (" if (key <= MAX_HASH_VALUE && key >= 0)\n"); + + if (option[DUP]) + { + int indent = 8; + printf ("%*s{\n" + "%*s register int index = lookup[key];\n\n" + "%*s if (index >= 0)\n", + indent, "", indent, "", indent, ""); + if (option[LENTABLE]) + { + printf ("%*s {\n" + "%*s if (len == lengthtable[index])\n", + indent, "", indent, ""); + indent += 4; + } + printf ("%*s {\n" + "%*s register %schar *s = %s[index]", + indent, "", + indent, "", const_always, option.get_wordlist_name ()); + if (option[TYPE]) + printf (".%s", option.get_slot_name ()); + if (option[SHAREDLIB]) + printf (" + %s", + option.get_stringpool_name ()); + printf (";\n\n" + "%*s if (", + indent, ""); + comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); + printf (")\n" + "%*s return ", + indent, ""); + if (option[TYPE]) + printf ("&%s[index]", option.get_wordlist_name ()); + else + printf ("s"); + printf (";\n" + "%*s }\n", + indent, ""); + if (option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", indent, ""); + } + if (_total_duplicates > 0) + { + printf ("%*s else if (index < -TOTAL_KEYWORDS)\n" + "%*s {\n" + "%*s register int offset = - 1 - TOTAL_KEYWORDS - index;\n", + indent, "", indent, "", indent, ""); + if (option[LENTABLE]) + printf ("%*s register %s%s *lengthptr = &lengthtable[TOTAL_KEYWORDS + lookup[offset]];\n", + indent, "", const_always, smallest_integral_type (_max_key_len)); + printf ("%*s register ", + indent, ""); + output_const_type (const_readonly_array, _wordlist_eltype); + printf ("*wordptr = &%s[TOTAL_KEYWORDS + lookup[offset]];\n", + option.get_wordlist_name ()); + printf ("%*s register ", + indent, ""); + output_const_type (const_readonly_array, _wordlist_eltype); + printf ("*wordendptr = wordptr + -lookup[offset + 1];\n\n"); + printf ("%*s while (wordptr < wordendptr)\n" + "%*s {\n", + indent, "", indent, ""); + if (option[LENTABLE]) + { + printf ("%*s if (len == *lengthptr)\n" + "%*s {\n", + indent, "", indent, ""); + indent += 4; + } + printf ("%*s register %schar *s = ", + indent, "", const_always); + if (option[TYPE]) + printf ("wordptr->%s", option.get_slot_name ()); + else + printf ("*wordptr"); + if (option[SHAREDLIB]) + printf (" + %s", + option.get_stringpool_name ()); + printf (";\n\n" + "%*s if (", + indent, ""); + comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); + printf (")\n" + "%*s return %s;\n", + indent, "", + option[TYPE] ? "wordptr" : "s"); + if (option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", + indent, ""); + } + if (option[LENTABLE]) + printf ("%*s lengthptr++;\n", + indent, ""); + printf ("%*s wordptr++;\n" + "%*s }\n" + "%*s }\n", + indent, "", indent, "", indent, ""); + } + printf ("%*s}\n", + indent, ""); + } + else + { + int indent = 8; + if (option[LENTABLE]) + { + printf ("%*sif (len == lengthtable[key])\n", + indent, ""); + indent += 2; + } + + if (option[SHAREDLIB]) + { + if (!option[LENTABLE]) + { + printf ("%*s{\n" + "%*s register int o = %s[key]", + indent, "", + indent, "", option.get_wordlist_name ()); + if (option[TYPE]) + printf (".%s", option.get_slot_name ()); + printf (";\n" + "%*s if (o >= 0)\n" + "%*s {\n", + indent, "", + indent, ""); + indent += 4; + printf ("%*s register %schar *s = o", + indent, "", const_always); + } + else + { + /* No need for the (o >= 0) test, because the + (len == lengthtable[key]) test already guarantees that + key points to nonempty table entry. */ + printf ("%*s{\n" + "%*s register %schar *s = %s[key]", + indent, "", + indent, "", const_always, + option.get_wordlist_name ()); + if (option[TYPE]) + printf (".%s", option.get_slot_name ()); + } + printf (" + %s", + option.get_stringpool_name ()); + } + else + { + printf ("%*s{\n" + "%*s register %schar *s = %s[key]", + indent, "", + indent, "", const_always, option.get_wordlist_name ()); + if (option[TYPE]) + printf (".%s", option.get_slot_name ()); + } + + printf (";\n\n" + "%*s if (", + indent, ""); + if (!option[SHAREDLIB] && option[NULLSTRINGS]) + printf ("s && "); + comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); + printf (")\n" + "%*s return ", + indent, ""); + if (option[TYPE]) + printf ("&%s[key]", option.get_wordlist_name ()); + else + printf ("s"); + printf (";\n"); + if (option[SHAREDLIB] && !option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", + indent, ""); + } + printf ("%*s}\n", + indent, ""); + } + } + printf (" }\n" + " return 0;\n"); +} + +/* Generates C code for the lookup function. */ + +void +Output::output_lookup_function () const +{ + /* Output the function's head. */ + if (option[KRC] | option[C] | option[ANSIC]) + printf ("#ifdef __GNUC__\n" + "__inline\n" + "#endif\n"); + + printf ("%s%s\n", + const_for_struct, _return_type); + if (option[CPLUSPLUS]) + printf ("%s::", option.get_class_name ()); + printf ("%s ", option.get_function_name ()); + printf (option[KRC] ? + "(str, len)\n" + " register char *str;\n" + " register unsigned int len;\n" : + option[C] ? + "(str, len)\n" + " register const char *str;\n" + " register unsigned int len;\n" : + option[ANSIC] | option[CPLUSPLUS] ? + "(register const char *str, register unsigned int len)\n" : + ""); + + /* Output the function's body. */ + printf ("{\n"); + + if (option[ENUM] && !option[GLOBAL]) + { + Output_Enum style (" "); + output_constants (style); + } + + if (option[SHAREDLIB] && !(option[GLOBAL] || option[TYPE])) + output_lookup_pools (); + if (!option[GLOBAL]) + output_lookup_tables (); + + if (option[LENTABLE]) + output_lookup_function_body (Output_Compare_Memcmp ()); + else + { + if (option[COMP]) + output_lookup_function_body (Output_Compare_Strncmp ()); + else + output_lookup_function_body (Output_Compare_Strcmp ()); + } + + printf ("}\n"); +} + +/* ------------------------------------------------------------------------- */ + +/* Generates the hash function and the key word recognizer function + based upon the user's Options. */ + +void +Output::output () +{ + compute_min_max (); + + if (option[C] | option[ANSIC] | option[CPLUSPLUS]) + { + const_always = "const "; + const_readonly_array = (option[CONST] ? "const " : ""); + const_for_struct = ((option[CONST] && option[TYPE]) ? "const " : ""); + } + else + { + const_always = ""; + const_readonly_array = ""; + const_for_struct = ""; + } + + if (!option[TYPE]) + { + _return_type = (const_always[0] ? "const char *" : "char *"); + _struct_tag = (const_always[0] ? "const char *" : "char *"); + } + + _wordlist_eltype = (option[SHAREDLIB] && !option[TYPE] ? "int" : _struct_tag); + + printf ("/* "); + if (option[KRC]) + printf ("KR-C"); + else if (option[C]) + printf ("C"); + else if (option[ANSIC]) + printf ("ANSI-C"); + else if (option[CPLUSPLUS]) + printf ("C++"); + printf (" code produced by gperf version %s */\n", version_string); + option.print_options (); + printf ("\n"); + if (!option[POSITIONS]) + { + printf ("/* Computed positions: -k'"); + _key_positions.print(); + printf ("' */\n"); + } + printf ("\n"); + + if (_charset_dependent + && (_key_positions.get_size() > 0 || option[UPPERLOWER])) + { + /* The generated tables assume that the execution character set is + based on ISO-646, not EBCDIC. */ + printf ("#if !((' ' == 32) && ('!' == 33) && ('\"' == 34) && ('#' == 35) \\\n" + " && ('%%' == 37) && ('&' == 38) && ('\\'' == 39) && ('(' == 40) \\\n" + " && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \\\n" + " && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \\\n" + " && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \\\n" + " && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \\\n" + " && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \\\n" + " && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \\\n" + " && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \\\n" + " && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \\\n" + " && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \\\n" + " && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \\\n" + " && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \\\n" + " && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \\\n" + " && ('Z' == 90) && ('[' == 91) && ('\\\\' == 92) && (']' == 93) \\\n" + " && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \\\n" + " && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \\\n" + " && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \\\n" + " && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \\\n" + " && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \\\n" + " && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \\\n" + " && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \\\n" + " && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))\n" + "/* The character set is not based on ISO-646. */\n"); + printf ("%s \"gperf generated tables don't work with this execution character set. Please report a bug to .\"\n", option[KRC] || option[C] ? "error" : "#error"); + printf ("#endif\n\n"); + } + + if (_verbatim_declarations < _verbatim_declarations_end) + { + if (option.get_input_file_name ()) + printf ("#line %u \"%s\"\n", + _verbatim_declarations_lineno, option.get_input_file_name ()); + fwrite (_verbatim_declarations, 1, + _verbatim_declarations_end - _verbatim_declarations, stdout); + } + + if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */ + { + if (option.get_input_file_name ()) + printf ("#line %u \"%s\"\n", + _struct_decl_lineno, option.get_input_file_name ()); + printf ("%s\n", _struct_decl); + } + + if (option[INCLUDE]) + printf ("#include \n"); /* Declare strlen(), strcmp(), strncmp(). */ + + if (!option[ENUM]) + { + Output_Defines style; + output_constants (style); + } + else if (option[GLOBAL]) + { + Output_Enum style (""); + output_constants (style); + } + + printf ("/* maximum key range = %d, duplicates = %d */\n\n", + _max_hash_value - _min_hash_value + 1, _total_duplicates); + + if (option[UPPERLOWER]) + { + #if USE_DOWNCASE_TABLE + output_upperlower_table (); + #endif + + if (option[LENTABLE]) + output_upperlower_memcmp (); + else + { + if (option[COMP]) + output_upperlower_strncmp (); + else + output_upperlower_strcmp (); + } + } + + if (option[CPLUSPLUS]) + printf ("class %s\n" + "{\n" + "private:\n" + " static inline unsigned int %s (const char *str, unsigned int len);\n" + "public:\n" + " static %s%s%s (const char *str, unsigned int len);\n" + "};\n" + "\n", + option.get_class_name (), option.get_hash_name (), + const_for_struct, _return_type, option.get_function_name ()); + + output_hash_function (); + + if (option[SHAREDLIB] && (option[GLOBAL] || option[TYPE])) + output_lookup_pools (); + if (option[GLOBAL]) + output_lookup_tables (); + + output_lookup_function (); + + if (_verbatim_code < _verbatim_code_end) + { + if (option.get_input_file_name ()) + printf ("#line %u \"%s\"\n", + _verbatim_code_lineno, option.get_input_file_name ()); + fwrite (_verbatim_code, 1, _verbatim_code_end - _verbatim_code, stdout); + } + + fflush (stdout); +} diff --git a/contrib/gperf-3.0.1/src/output.h b/contrib/gperf-3.0.1/src/output.h new file mode 100644 index 0000000000..9dd5ba2b61 --- /dev/null +++ b/contrib/gperf-3.0.1/src/output.h @@ -0,0 +1,154 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Output routines. + + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef output_h +#define output_h 1 + +#include "keyword-list.h" +#include "positions.h" + +/* OSF/1 cxx needs these forward declarations. */ +struct Output_Constants; +struct Output_Compare; + +class Output +{ +public: + /* Constructor. */ + Output (KeywordExt_List *head, + const char *struct_decl, + unsigned int struct_decl_lineno, + const char *return_type, + const char *struct_tag, + const char *verbatim_declarations, + const char *verbatim_declarations_end, + unsigned int verbatim_declarations_lineno, + const char *verbatim_code, + const char *verbatim_code_end, + unsigned int verbatim_code_lineno, + bool charset_dependent, + int total_keys, + int max_key_len, int min_key_len, + const Positions& positions, + const unsigned int *alpha_inc, + int total_duplicates, + unsigned int alpha_size, + const int *asso_values); + + /* Generates the hash function and the key word recognizer function. */ + void output (); + +private: + + /* Computes the minimum and maximum hash values, and stores them + in _min_hash_value and _max_hash_value. */ + void compute_min_max (); + + /* Returns the number of different hash values. */ + int num_hash_values () const; + + /* Outputs the maximum and minimum hash values etc. */ + void output_constants (struct Output_Constants&) const; + + /* Generates a C expression for an asso_values[] reference. */ + void output_asso_values_ref (int pos) const; + + /* Generates C code for the hash function that returns the + proper encoding for each keyword. */ + void output_hash_function () const; + + /* Prints out a table of keyword lengths, for use with the + comparison code in generated function 'in_word_set'. */ + void output_keylength_table () const; + + /* Prints out the string pool, containing the strings of the keyword table. + */ + void output_string_pool () const; + + /* Prints out the array containing the keywords for the hash function. */ + void output_keyword_table () const; + + /* Generates the large, sparse table that maps hash values into + the smaller, contiguous range of the keyword table. */ + void output_lookup_array () const; + + /* Generate all pools needed for the lookup function. */ + void output_lookup_pools () const; + + /* Generate all the tables needed for the lookup function. */ + void output_lookup_tables () const; + + /* Generates C code to perform the keyword lookup. */ + void output_lookup_function_body (const struct Output_Compare&) const; + + /* Generates C code for the lookup function. */ + void output_lookup_function () const; + + /* Linked list of keywords. */ + KeywordExt_List * _head; + + /* Declaration of struct type for a keyword and its attributes. */ + const char * const _struct_decl; + unsigned int const _struct_decl_lineno; + /* Pointer to return type for lookup function. */ + const char * _return_type; + /* Shorthand for user-defined struct tag type. */ + const char * _struct_tag; + /* Element type of keyword array. */ + const char * _wordlist_eltype; + /* The C code from the declarations section. */ + const char * const _verbatim_declarations; + const char * const _verbatim_declarations_end; + unsigned int const _verbatim_declarations_lineno; + /* The C code from the end of the file. */ + const char * const _verbatim_code; + const char * const _verbatim_code_end; + unsigned int const _verbatim_code_lineno; + /* Whether the keyword chars would have different values in a different + character set. */ + bool _charset_dependent; + /* Total number of keys, counting duplicates. */ + int const _total_keys; + /* Maximum length of the longest keyword. */ + int const _max_key_len; + /* Minimum length of the shortest keyword. */ + int const _min_key_len; + /* Key positions. */ + Positions const _key_positions; + /* Adjustments to add to bytes add specific key positions. */ + const unsigned int * const _alpha_inc; + /* Total number of duplicate hash values. */ + int const _total_duplicates; + /* Minimum hash value for all keywords. */ + int _min_hash_value; + /* Maximum hash value for all keywords. */ + int _max_hash_value; + /* Size of alphabet. */ + unsigned int const _alpha_size; + /* Value associated with each character. */ + const int * const _asso_values; +}; + +#endif diff --git a/contrib/gperf-3.0.1/src/positions.cc b/contrib/gperf-3.0.1/src/positions.cc new file mode 100644 index 0000000000..f6439e3fa2 --- /dev/null +++ b/contrib/gperf-3.0.1/src/positions.cc @@ -0,0 +1,177 @@ +/* A set of byte positions. + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "positions.h" + +#include +#include /* declares exit() */ +#include + +/* ---------------------------- Class Positions ---------------------------- */ + +/* Set operations. Assumes the array is in reverse order. */ + +bool +Positions::contains (int pos) const +{ + unsigned int count = _size; + const int *p = _positions + _size - 1; + + for (; count > 0; p--, count--) + { + if (*p == pos) + return true; + if (*p > pos) + break; + } + return false; +} + +void +Positions::add (int pos) +{ + set_useall (false); + + unsigned int count = _size; + + if (count == MAX_SIZE) + { + fprintf (stderr, "Positions::add internal error: overflow\n"); + exit (1); + } + + int *p = _positions + _size - 1; + + for (; count > 0; p--, count--) + { + if (*p == pos) + { + fprintf (stderr, "Positions::add internal error: duplicate\n"); + exit (1); + } + if (*p > pos) + break; + p[1] = p[0]; + } + p[1] = pos; + _size++; +} + +void +Positions::remove (int pos) +{ + set_useall (false); + + unsigned int count = _size; + if (count > 0) + { + int *p = _positions + _size - 1; + + if (*p == pos) + { + _size--; + return; + } + if (*p < pos) + { + int prev = *p; + + for (;;) + { + p--; + count--; + if (count == 0) + break; + if (*p == pos) + { + *p = prev; + _size--; + return; + } + if (*p > pos) + break; + int curr = *p; + *p = prev; + prev = curr; + } + } + } + fprintf (stderr, "Positions::remove internal error: not found\n"); + exit (1); +} + +/* Output in external syntax. */ +void +Positions::print () const +{ + if (_useall) + printf ("*"); + else + { + bool first = true; + bool seen_LASTCHAR = false; + unsigned int count = _size; + const int *p = _positions + _size - 1; + + for (; count > 0; p--) + { + count--; + if (*p == LASTCHAR) + seen_LASTCHAR = true; + else + { + if (!first) + printf (","); + printf ("%d", *p + 1); + if (count > 0 && p[-1] == *p + 1) + { + printf ("-"); + do + { + p--; + count--; + } + while (count > 0 && p[-1] == *p + 1); + printf ("%d", *p + 1); + } + first = false; + } + } + if (seen_LASTCHAR) + { + if (!first) + printf (","); + printf ("$"); + } + } +} + +/* ------------------------------------------------------------------------- */ + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "positions.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/contrib/gperf-3.0.1/src/positions.h b/contrib/gperf-3.0.1/src/positions.h new file mode 100644 index 0000000000..d16c214293 --- /dev/null +++ b/contrib/gperf-3.0.1/src/positions.h @@ -0,0 +1,171 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* A set of byte positions. + + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef positions_h +#define positions_h 1 + +/* This class denotes a set of byte positions, used to access a keyword. */ + +class Positions +{ + friend class PositionIterator; + friend class PositionReverseIterator; +public: + /* Denotes the last char of a keyword, depending on the keyword's length. */ + enum { LASTCHAR = -1 }; + + /* Maximum key position specifiable by the user, 1-based. + Note that MAX_KEY_POS-1 must fit into the element type of _positions[], + below. */ + enum { MAX_KEY_POS = 255 }; + + /* Maximum possible size. Since duplicates are eliminated and the possible + 0-based positions are -1 .. MAX_KEY_POS-1, this is: */ + enum { MAX_SIZE = MAX_KEY_POS + 1 }; + + /* Constructors. */ + Positions (); + Positions (int pos1); + Positions (int pos1, int pos2); + + /* Copy constructor. */ + Positions (const Positions& src); + + /* Assignment operator. */ + Positions& operator= (const Positions& src); + + /* Accessors. */ + bool is_useall () const; + int operator[] (unsigned int index) const; + unsigned int get_size () const; + + /* Write access. */ + void set_useall (bool useall); + int * pointer (); + void set_size (unsigned int size); + + /* Sorts the array in reverse order. + Returns true if there are no duplicates, false otherwise. */ + bool sort (); + + /* Creates an iterator, returning the positions in descending order. */ + PositionIterator iterator () const; + /* Creates an iterator, returning the positions in descending order, + that apply to strings of length <= maxlen. */ + PositionIterator iterator (int maxlen) const; + /* Creates an iterator, returning the positions in ascending order. */ + PositionReverseIterator reviterator () const; + /* Creates an iterator, returning the positions in ascending order, + that apply to strings of length <= maxlen. */ + PositionReverseIterator reviterator (int maxlen) const; + + /* Set operations. Assumes the array is in reverse order. */ + bool contains (int pos) const; + void add (int pos); + void remove (int pos); + + /* Output in external syntax. */ + void print () const; + +private: + /* The special case denoted by '*'. */ + bool _useall; + /* Number of positions. */ + unsigned int _size; + /* Array of positions. 0 for the first char, 1 for the second char etc., + LASTCHAR for the last char. */ + int _positions[MAX_SIZE]; +}; + +/* This class denotes an iterator through a set of byte positions. */ + +class PositionIterator +{ + friend class Positions; +public: + /* Copy constructor. */ + PositionIterator (const PositionIterator& src); + + /* End of iteration marker. */ + enum { EOS = -2 }; + + /* Retrieves the next position, or EOS past the end. */ + int next (); + + /* Returns the number of remaining positions, i.e. how often next() will + return a value != EOS. */ + unsigned int remaining () const; + +private: + /* Initializes an iterator through POSITIONS. */ + PositionIterator (Positions const& positions); + /* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */ + PositionIterator (Positions const& positions, int maxlen); + + const Positions& _set; + unsigned int _index; +}; + +/* This class denotes an iterator in reverse direction through a set of + byte positions. */ + +class PositionReverseIterator +{ + friend class Positions; +public: + /* Copy constructor. */ + PositionReverseIterator (const PositionReverseIterator& src); + + /* End of iteration marker. */ + enum { EOS = -2 }; + + /* Retrieves the next position, or EOS past the end. */ + int next (); + + /* Returns the number of remaining positions, i.e. how often next() will + return a value != EOS. */ + unsigned int remaining () const; + +private: + /* Initializes an iterator through POSITIONS. */ + PositionReverseIterator (Positions const& positions); + /* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */ + PositionReverseIterator (Positions const& positions, int maxlen); + + const Positions& _set; + unsigned int _index; + unsigned int _minindex; +}; + +#ifdef __OPTIMIZE__ + +#include +#define INLINE inline +#include "positions.icc" +#undef INLINE + +#endif + +#endif diff --git a/contrib/gperf-3.0.1/src/positions.icc b/contrib/gperf-3.0.1/src/positions.icc new file mode 100644 index 0000000000..ca9347df94 --- /dev/null +++ b/contrib/gperf-3.0.1/src/positions.icc @@ -0,0 +1,285 @@ +/* Inline Functions for positions.{h,cc}. + + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +// This needs: +//#include + +/* ---------------------------- Class Positions ---------------------------- */ + +/* Constructors. */ + +INLINE +Positions::Positions () + : _useall (false), + _size (0) +{ +} + +INLINE +Positions::Positions (int pos1) + : _useall (false), + _size (1) +{ + _positions[0] = pos1; +} + +INLINE +Positions::Positions (int pos1, int pos2) + : _useall (false), + _size (2) +{ + _positions[0] = pos1; + _positions[1] = pos2; +} + +/* Copy constructor. */ + +INLINE +Positions::Positions (const Positions& src) + : _useall (src._useall), + _size (src._size) +{ + memcpy (_positions, src._positions, _size * sizeof (_positions[0])); +} + +/* Assignment operator. */ + +INLINE Positions& +Positions::operator= (const Positions& src) +{ + _useall = src._useall; + _size = src._size; + memcpy (_positions, src._positions, _size * sizeof (_positions[0])); + return *this; +} + +/* Accessors. */ + +INLINE bool +Positions::is_useall () const +{ + return _useall; +} + +INLINE int +Positions::operator[] (unsigned int index) const +{ + return _positions[index]; +} + +INLINE unsigned int +Positions::get_size () const +{ + return _size; +} + +/* Write access. */ + +INLINE void +Positions::set_useall (bool useall) +{ + _useall = useall; + if (useall) + { + /* The positions are 0, 1, ..., MAX_KEY_POS-1, in descending order. */ + _size = MAX_KEY_POS; + int *ptr = _positions; + for (int i = MAX_KEY_POS - 1; i >= 0; i--) + *ptr++ = i; + } +} + +INLINE int * +Positions::pointer () +{ + return _positions; +} + +INLINE void +Positions::set_size (unsigned int size) +{ + _size = size; +} + +/* Sorts the array in reverse order. + Returns true if there are no duplicates, false otherwise. */ +INLINE bool +Positions::sort () +{ + if (_useall) + return true; + + /* Bubble sort. */ + bool duplicate_free = true; + int *base = _positions; + unsigned int len = _size; + + for (unsigned int i = 1; i < len; i++) + { + unsigned int j; + int tmp; + + for (j = i, tmp = base[j]; j > 0 && tmp >= base[j - 1]; j--) + if ((base[j] = base[j - 1]) == tmp) /* oh no, a duplicate!!! */ + duplicate_free = false; + + base[j] = tmp; + } + + return duplicate_free; +} + +/* Creates an iterator, returning the positions in descending order. */ +INLINE PositionIterator +Positions::iterator () const +{ + return PositionIterator (*this); +} + +/* Creates an iterator, returning the positions in descending order, + that apply to strings of length <= maxlen. */ +INLINE PositionIterator +Positions::iterator (int maxlen) const +{ + return PositionIterator (*this, maxlen); +} + +/* Creates an iterator, returning the positions in ascending order. */ +INLINE PositionReverseIterator +Positions::reviterator () const +{ + return PositionReverseIterator (*this); +} + +/* Creates an iterator, returning the positions in ascending order, + that apply to strings of length <= maxlen. */ +INLINE PositionReverseIterator +Positions::reviterator (int maxlen) const +{ + return PositionReverseIterator (*this, maxlen); +} + +/* ------------------------- Class PositionIterator ------------------------ */ + +/* Initializes an iterator through POSITIONS. */ +INLINE +PositionIterator::PositionIterator (Positions const& positions) + : _set (positions), + _index (0) +{ +} + +/* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */ +INLINE +PositionIterator::PositionIterator (Positions const& positions, int maxlen) + : _set (positions) +{ + if (positions._useall) + _index = (maxlen <= Positions::MAX_KEY_POS ? Positions::MAX_KEY_POS - maxlen : 0); + else + { + unsigned int index; + for (index = 0; + index < positions._size && positions._positions[index] >= maxlen; + index++) + ; + _index = index; + } +} + +/* Retrieves the next position, or EOS past the end. */ +INLINE int +PositionIterator::next () +{ + return (_index < _set._size ? _set._positions[_index++] : EOS); +} + +/* Returns the number of remaining positions, i.e. how often next() will + return a value != EOS. */ +INLINE unsigned int +PositionIterator::remaining () const +{ + return _set._size - _index; +} + +/* Copy constructor. */ +INLINE +PositionIterator::PositionIterator (const PositionIterator& src) + : _set (src._set), + _index (src._index) +{ +} + +/* --------------------- Class PositionReverseIterator --------------------- */ + +/* Initializes an iterator through POSITIONS. */ +INLINE +PositionReverseIterator::PositionReverseIterator (Positions const& positions) + : _set (positions), + _index (_set._size), + _minindex (0) +{ +} + +/* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */ +INLINE +PositionReverseIterator::PositionReverseIterator (Positions const& positions, int maxlen) + : _set (positions), + _index (_set._size) +{ + if (positions._useall) + _minindex = (maxlen <= Positions::MAX_KEY_POS ? Positions::MAX_KEY_POS - maxlen : 0); + else + { + unsigned int index; + for (index = 0; + index < positions._size && positions._positions[index] >= maxlen; + index++) + ; + _minindex = index; + } +} + +/* Retrieves the next position, or EOS past the end. */ +INLINE int +PositionReverseIterator::next () +{ + return (_index > _minindex ? _set._positions[--_index] : EOS); +} + +/* Returns the number of remaining positions, i.e. how often next() will + return a value != EOS. */ +INLINE unsigned int +PositionReverseIterator::remaining () const +{ + return _index - _minindex; +} + +/* Copy constructor. */ +INLINE +PositionReverseIterator::PositionReverseIterator (const PositionReverseIterator& src) + : _set (src._set), + _index (src._index), + _minindex (src._minindex) +{ +} diff --git a/contrib/gperf-3.0.1/src/search.cc b/contrib/gperf-3.0.1/src/search.cc new file mode 100644 index 0000000000..6eec1bb530 --- /dev/null +++ b/contrib/gperf-3.0.1/src/search.cc @@ -0,0 +1,1684 @@ +/* Search algorithm. + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "search.h" + +#include +#include /* declares exit(), rand(), srand() */ +#include /* declares memset(), memcmp() */ +#include /* declares time() */ +#include /* declares exp() */ +#include /* defines INT_MIN, INT_MAX, UINT_MAX */ +#include "options.h" +#include "hash-table.h" +#include "config.h" + +/* ============================== Portability ============================== */ + +/* Assume ISO C++ 'for' scoping rule. */ +#define for if (0) ; else for + +/* Dynamically allocated array with dynamic extent: + + Example: + DYNAMIC_ARRAY (my_array, int, n); + ... + FREE_DYNAMIC_ARRAY (my_array); + + Attention: depending on your implementation my_array is either the array + itself or a pointer to the array! Always use my_array only as expression! + */ +#if HAVE_DYNAMIC_ARRAY + #define DYNAMIC_ARRAY(var,eltype,size) eltype var[size] + #define FREE_DYNAMIC_ARRAY(var) +#else + #define DYNAMIC_ARRAY(var,eltype,size) eltype *var = new eltype[size] + #define FREE_DYNAMIC_ARRAY(var) delete[] var +#endif + +/* ================================ Theory ================================= */ + +/* The general form of the hash function is + + hash (keyword) = sum (asso_values[keyword[i] + alpha_inc[i]] : i in Pos) + + len (keyword) + + where Pos is a set of byte positions, + each alpha_inc[i] is a nonnegative integer, + each asso_values[c] is a nonnegative integer, + len (keyword) is the keyword's length if !option[NOLENGTH], or 0 otherwise. + + Theorem 1: If all keywords are different, there is a set Pos such that + all tuples (keyword[i] : i in Pos) are different. + + Theorem 2: If all tuples (keyword[i] : i in Pos) are different, there + are nonnegative integers alpha_inc[i] such that all multisets + {keyword[i] + alpha_inc[i] : i in Pos} are different. + + Define selchars[keyword] := {keyword[i] + alpha_inc[i] : i in Pos}. + + Theorem 3: If all multisets selchars[keyword] are different, there are + nonnegative integers asso_values[c] such that all hash values + sum (asso_values[c] : c in selchars[keyword]) are different. + + Based on these three facts, we find the hash function in three steps: + + Step 1 (Finding good byte positions): + Find a set Pos, as small as possible, such that all tuples + (keyword[i] : i in Pos) are different. + + Step 2 (Finding good alpha increments): + Find nonnegative integers alpha_inc[i], as many of them as possible being + zero, and the others being as small as possible, such that all multisets + {keyword[i] + alpha_inc[i] : i in Pos} are different. + + Step 3 (Finding good asso_values): + Find asso_values[c] such that all hash (keyword) are different. + + In other words, each step finds a projection that is injective on the + given finite set: + proj1 : String --> Map (Pos --> N) + proj2 : Map (Pos --> N) --> Map (Pos --> N) / S(Pos) + proj3 : Map (Pos --> N) / S(Pos) --> N + where + N denotes the set of nonnegative integers, + Map (A --> B) := Hom_Set (A, B) is the set of maps from A to B, and + S(Pos) is the symmetric group over Pos. + + This was the theory for option[NOLENGTH]; if !option[NOLENGTH], slight + modifications apply: + proj1 : String --> Map (Pos --> N) x N + proj2 : Map (Pos --> N) x N --> Map (Pos --> N) / S(Pos) x N + proj3 : Map (Pos --> N) / S(Pos) x N --> N + + For a case-insensitive hash function, the general form is + + hash (keyword) = + sum (asso_values[alpha_unify[keyword[i] + alpha_inc[i]]] : i in Pos) + + len (keyword) + + where alpha_unify[c] is chosen so that an upper/lower case change in + keyword[i] doesn't change alpha_unify[keyword[i] + alpha_inc[i]]. + */ + +/* ==================== Initialization and Preparation ===================== */ + +Search::Search (KeywordExt_List *list) + : _head (list) +{ +} + +void +Search::prepare () +{ + /* Compute the total number of keywords. */ + _total_keys = 0; + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + _total_keys++; + + /* Compute the minimum and maximum keyword length. */ + _max_key_len = INT_MIN; + _min_key_len = INT_MAX; + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + if (_max_key_len < keyword->_allchars_length) + _max_key_len = keyword->_allchars_length; + if (_min_key_len > keyword->_allchars_length) + _min_key_len = keyword->_allchars_length; + } + + /* Exit program if an empty string is used as keyword, since the comparison + expressions don't work correctly for looking up an empty string. */ + if (_min_key_len == 0) + { + fprintf (stderr, "Empty input keyword is not allowed.\n" + "To recognize an empty input keyword, your code should check for\n" + "len == 0 before calling the gperf generated lookup function.\n"); + exit (1); + } + + /* Exit program if the characters in the keywords are not in the required + range. */ + if (option[SEVENBIT]) + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + const char *k = keyword->_allchars; + for (int i = keyword->_allchars_length; i > 0; k++, i--) + if (!(static_cast(*k) < 128)) + { + fprintf (stderr, "Option --seven-bit has been specified,\n" + "but keyword \"%.*s\" contains non-ASCII characters.\n" + "Try removing option --seven-bit.\n", + keyword->_allchars_length, keyword->_allchars); + exit (1); + } + } +} + +/* ====================== Finding good byte positions ====================== */ + +/* Computes the upper bound on the indices passed to asso_values[], + assuming no alpha_increments. */ +unsigned int +Search::compute_alpha_size () const +{ + return (option[SEVENBIT] ? 128 : 256); +} + +/* Computes the unification rules between different asso_values[c], + assuming no alpha_increments. */ +unsigned int * +Search::compute_alpha_unify () const +{ + if (option[UPPERLOWER]) + { + /* Uppercase to lowercase mapping. */ + unsigned int alpha_size = compute_alpha_size(); + unsigned int *alpha_unify = new unsigned int[alpha_size]; + for (unsigned int c = 0; c < alpha_size; c++) + alpha_unify[c] = c; + for (unsigned int c = 'A'; c <= 'Z'; c++) + alpha_unify[c] = c + ('a'-'A'); + return alpha_unify; + } + else + /* Identity mapping. */ + return NULL; +} + +/* Initializes each keyword's _selchars array. */ +void +Search::init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify) const +{ + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + temp->first()->init_selchars_tuple(positions, alpha_unify); +} + +/* Deletes each keyword's _selchars array. */ +void +Search::delete_selchars () const +{ + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + temp->first()->delete_selchars(); +} + +/* Count the duplicate keywords that occur with a given set of positions. + In other words, it returns the difference + # K - # proj1 (K) + where K is the multiset of given keywords. */ +unsigned int +Search::count_duplicates_tuple (const Positions& positions, const unsigned int *alpha_unify) const +{ + /* Run through the keyword list and count the duplicates incrementally. + The result does not depend on the order of the keyword list, thanks to + the formula above. */ + init_selchars_tuple (positions, alpha_unify); + + unsigned int count = 0; + { + Hash_Table representatives (_total_keys, option[NOLENGTH]); + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + if (representatives.insert (keyword)) + count++; + } + } + + delete_selchars (); + + return count; +} + +/* Find good key positions. */ + +void +Search::find_positions () +{ + /* If the user gave the key positions, we use them. */ + if (option[POSITIONS]) + { + _key_positions = option.get_key_positions(); + return; + } + + /* Compute preliminary alpha_unify table. */ + unsigned int *alpha_unify = compute_alpha_unify (); + + /* 1. Find positions that must occur in order to distinguish duplicates. */ + Positions mandatory; + + if (!option[DUP]) + { + for (KeywordExt_List *l1 = _head; l1 && l1->rest(); l1 = l1->rest()) + { + KeywordExt *keyword1 = l1->first(); + for (KeywordExt_List *l2 = l1->rest(); l2; l2 = l2->rest()) + { + KeywordExt *keyword2 = l2->first(); + + /* If keyword1 and keyword2 have the same length and differ + in just one position, and it is not the last character, + this position is mandatory. */ + if (keyword1->_allchars_length == keyword2->_allchars_length) + { + int n = keyword1->_allchars_length; + int i; + for (i = 0; i < n - 1; i++) + { + unsigned char c1 = keyword1->_allchars[i]; + unsigned char c2 = keyword2->_allchars[i]; + if (option[UPPERLOWER]) + { + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + break; + } + if (i < n - 1) + { + int j; + for (j = i + 1; j < n; j++) + { + unsigned char c1 = keyword1->_allchars[j]; + unsigned char c2 = keyword2->_allchars[j]; + if (option[UPPERLOWER]) + { + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + break; + } + if (j >= n) + { + /* Position i is mandatory. */ + if (!mandatory.contains (i)) + mandatory.add (i); + } + } + } + } + } + } + + /* 2. Add positions, as long as this decreases the duplicates count. */ + int imax = (_max_key_len - 1 < Positions::MAX_KEY_POS - 1 + ? _max_key_len - 1 : Positions::MAX_KEY_POS - 1); + Positions current = mandatory; + unsigned int current_duplicates_count = + count_duplicates_tuple (current, alpha_unify); + for (;;) + { + Positions best; + unsigned int best_duplicates_count = UINT_MAX; + + for (int i = imax; i >= -1; i--) + if (!current.contains (i)) + { + Positions tryal = current; + tryal.add (i); + unsigned int try_duplicates_count = + count_duplicates_tuple (tryal, alpha_unify); + + /* We prefer 'try' to 'best' if it produces less duplicates, + or if it produces the same number of duplicates but with + a more efficient hash function. */ + if (try_duplicates_count < best_duplicates_count + || (try_duplicates_count == best_duplicates_count && i >= 0)) + { + best = tryal; + best_duplicates_count = try_duplicates_count; + } + } + + /* Stop adding positions when it gives no improvement. */ + if (best_duplicates_count >= current_duplicates_count) + break; + + current = best; + current_duplicates_count = best_duplicates_count; + } + + /* 3. Remove positions, as long as this doesn't increase the duplicates + count. */ + for (;;) + { + Positions best; + unsigned int best_duplicates_count = UINT_MAX; + + for (int i = imax; i >= -1; i--) + if (current.contains (i) && !mandatory.contains (i)) + { + Positions tryal = current; + tryal.remove (i); + unsigned int try_duplicates_count = + count_duplicates_tuple (tryal, alpha_unify); + + /* We prefer 'try' to 'best' if it produces less duplicates, + or if it produces the same number of duplicates but with + a more efficient hash function. */ + if (try_duplicates_count < best_duplicates_count + || (try_duplicates_count == best_duplicates_count && i == -1)) + { + best = tryal; + best_duplicates_count = try_duplicates_count; + } + } + + /* Stop removing positions when it gives no improvement. */ + if (best_duplicates_count > current_duplicates_count) + break; + + current = best; + current_duplicates_count = best_duplicates_count; + } + + /* 4. Replace two positions by one, as long as this doesn't increase the + duplicates count. */ + for (;;) + { + Positions best; + unsigned int best_duplicates_count = UINT_MAX; + + for (int i1 = imax; i1 >= -1; i1--) + if (current.contains (i1) && !mandatory.contains (i1)) + for (int i2 = imax; i2 >= -1; i2--) + if (current.contains (i2) && !mandatory.contains (i2) && i2 != i1) + for (int i3 = imax; i3 >= 0; i3--) + if (!current.contains (i3)) + { + Positions tryal = current; + tryal.remove (i1); + tryal.remove (i2); + tryal.add (i3); + unsigned int try_duplicates_count = + count_duplicates_tuple (tryal, alpha_unify); + + /* We prefer 'try' to 'best' if it produces less duplicates, + or if it produces the same number of duplicates but with + a more efficient hash function. */ + if (try_duplicates_count < best_duplicates_count + || (try_duplicates_count == best_duplicates_count + && (i1 == -1 || i2 == -1 || i3 >= 0))) + { + best = tryal; + best_duplicates_count = try_duplicates_count; + } + } + + /* Stop removing positions when it gives no improvement. */ + if (best_duplicates_count > current_duplicates_count) + break; + + current = best; + current_duplicates_count = best_duplicates_count; + } + + /* That's it. Hope it's good enough. */ + _key_positions = current; + + if (option[DEBUG]) + { + /* Print the result. */ + fprintf (stderr, "\nComputed positions: "); + PositionReverseIterator iter = _key_positions.reviterator(); + bool seen_lastchar = false; + bool first = true; + for (int i; (i = iter.next ()) != PositionReverseIterator::EOS; ) + { + if (!first) + fprintf (stderr, ", "); + if (i == Positions::LASTCHAR) + seen_lastchar = true; + else + { + fprintf (stderr, "%d", i + 1); + first = false; + } + } + if (seen_lastchar) + { + if (!first) + fprintf (stderr, ", "); + fprintf (stderr, "$"); + } + fprintf (stderr, "\n"); + } + + /* Free preliminary alpha_unify table. */ + delete[] alpha_unify; +} + +/* Count the duplicate keywords that occur with the found set of positions. + In other words, it returns the difference + # K - # proj1 (K) + where K is the multiset of given keywords. */ +unsigned int +Search::count_duplicates_tuple () const +{ + unsigned int *alpha_unify = compute_alpha_unify (); + unsigned int count = count_duplicates_tuple (_key_positions, alpha_unify); + delete[] alpha_unify; + return count; +} + +/* ===================== Finding good alpha increments ===================== */ + +/* Computes the upper bound on the indices passed to asso_values[]. */ +unsigned int +Search::compute_alpha_size (const unsigned int *alpha_inc) const +{ + unsigned int max_alpha_inc = 0; + for (int i = 0; i < _max_key_len; i++) + if (max_alpha_inc < alpha_inc[i]) + max_alpha_inc = alpha_inc[i]; + return (option[SEVENBIT] ? 128 : 256) + max_alpha_inc; +} + +/* Computes the unification rules between different asso_values[c]. */ +unsigned int * +Search::compute_alpha_unify (const Positions& positions, const unsigned int *alpha_inc) const +{ + if (option[UPPERLOWER]) + { + /* Without alpha increments, we would simply unify + 'A' -> 'a', ..., 'Z' -> 'z'. + But when a keyword contains at position i a character c, + we have the constraint + asso_values[tolower(c) + alpha_inc[i]] == + asso_values[toupper(c) + alpha_inc[i]]. + This introduces a unification + toupper(c) + alpha_inc[i] -> tolower(c) + alpha_inc[i]. + Note that this unification can extend outside the range of + ASCII letters! But still every unified character pair is at + a distance of 'a'-'A' = 32, or (after chained unification) + at a multiple of 32. So in the end the alpha_unify vector has + the form c -> c + 32 * f(c) where f(c) is a nonnegative + integer. */ + unsigned int alpha_size = compute_alpha_size (alpha_inc); + + unsigned int *alpha_unify = new unsigned int[alpha_size]; + for (unsigned int c = 0; c < alpha_size; c++) + alpha_unify[c] = c; + + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + /* Iterate through the selected character positions. */ + PositionIterator iter = positions.iterator(keyword->_allchars_length); + + for (int i; (i = iter.next ()) != PositionIterator::EOS; ) + { + unsigned int c; + if (i == Positions::LASTCHAR) + c = static_cast(keyword->_allchars[keyword->_allchars_length - 1]); + else if (i < keyword->_allchars_length) + c = static_cast(keyword->_allchars[i]); + else + abort (); + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + if (c >= 'a' && c <= 'z') + { + if (i != Positions::LASTCHAR) + c += alpha_inc[i]; + /* Unify c with c - ('a'-'A'). */ + unsigned int d = alpha_unify[c]; + unsigned int b = c - ('a'-'A'); + for (int a = b; a >= 0 && alpha_unify[a] == b; a -= ('a'-'A')) + alpha_unify[a] = d; + } + } + } + return alpha_unify; + } + else + /* Identity mapping. */ + return NULL; +} + +/* Initializes each keyword's _selchars array. */ +void +Search::init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc) const +{ + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + temp->first()->init_selchars_multiset(positions, alpha_unify, alpha_inc); +} + +/* Count the duplicate keywords that occur with the given set of positions + and a given alpha_inc[] array. + In other words, it returns the difference + # K - # proj2 (proj1 (K)) + where K is the multiset of given keywords. */ +unsigned int +Search::count_duplicates_multiset (const unsigned int *alpha_inc) const +{ + /* Run through the keyword list and count the duplicates incrementally. + The result does not depend on the order of the keyword list, thanks to + the formula above. */ + unsigned int *alpha_unify = compute_alpha_unify (_key_positions, alpha_inc); + init_selchars_multiset (_key_positions, alpha_unify, alpha_inc); + + unsigned int count = 0; + { + Hash_Table representatives (_total_keys, option[NOLENGTH]); + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + if (representatives.insert (keyword)) + count++; + } + } + + delete_selchars (); + delete[] alpha_unify; + + return count; +} + +/* Find good _alpha_inc[]. */ + +void +Search::find_alpha_inc () +{ + /* The goal is to choose _alpha_inc[] such that it doesn't introduce + artificial duplicates. + In other words, the goal is # proj2 (proj1 (K)) = # proj1 (K). */ + unsigned int duplicates_goal = count_duplicates_tuple (); + + /* Start with zero increments. This is sufficient in most cases. */ + unsigned int *current = new unsigned int [_max_key_len]; + for (int i = 0; i < _max_key_len; i++) + current[i] = 0; + unsigned int current_duplicates_count = count_duplicates_multiset (current); + + if (current_duplicates_count > duplicates_goal) + { + /* Look which _alpha_inc[i] we are free to increment. */ + unsigned int nindices; + { + nindices = 0; + PositionIterator iter = _key_positions.iterator(_max_key_len); + for (;;) + { + int key_pos = iter.next (); + if (key_pos == PositionIterator::EOS) + break; + if (key_pos != Positions::LASTCHAR) + nindices++; + } + } + + DYNAMIC_ARRAY (indices, unsigned int, nindices); + { + unsigned int j = 0; + PositionIterator iter = _key_positions.iterator(_max_key_len); + for (;;) + { + int key_pos = iter.next (); + if (key_pos == PositionIterator::EOS) + break; + if (key_pos != Positions::LASTCHAR) + indices[j++] = key_pos; + } + if (!(j == nindices)) + abort (); + } + + /* Perform several rounds of searching for a good alpha increment. + Each round reduces the number of artificial collisions by adding + an increment in a single key position. */ + DYNAMIC_ARRAY (best, unsigned int, _max_key_len); + DYNAMIC_ARRAY (tryal, unsigned int, _max_key_len); + do + { + /* An increment of 1 is not always enough. Try higher increments + also. */ + for (unsigned int inc = 1; ; inc++) + { + unsigned int best_duplicates_count = UINT_MAX; + + for (unsigned int j = 0; j < nindices; j++) + { + memcpy (tryal, current, _max_key_len * sizeof (unsigned int)); + tryal[indices[j]] += inc; + unsigned int try_duplicates_count = + count_duplicates_multiset (tryal); + + /* We prefer 'try' to 'best' if it produces less + duplicates. */ + if (try_duplicates_count < best_duplicates_count) + { + memcpy (best, tryal, _max_key_len * sizeof (unsigned int)); + best_duplicates_count = try_duplicates_count; + } + } + + /* Stop this round when we got an improvement. */ + if (best_duplicates_count < current_duplicates_count) + { + memcpy (current, best, _max_key_len * sizeof (unsigned int)); + current_duplicates_count = best_duplicates_count; + break; + } + } + } + while (current_duplicates_count > duplicates_goal); + FREE_DYNAMIC_ARRAY (tryal); + FREE_DYNAMIC_ARRAY (best); + + if (option[DEBUG]) + { + /* Print the result. */ + fprintf (stderr, "\nComputed alpha increments: "); + bool first = true; + for (unsigned int j = nindices; j-- > 0; ) + if (current[indices[j]] != 0) + { + if (!first) + fprintf (stderr, ", "); + fprintf (stderr, "%u:+%u", + indices[j] + 1, current[indices[j]]); + first = false; + } + fprintf (stderr, "\n"); + } + FREE_DYNAMIC_ARRAY (indices); + } + + _alpha_inc = current; + _alpha_size = compute_alpha_size (_alpha_inc); + _alpha_unify = compute_alpha_unify (_key_positions, _alpha_inc); +} + +/* ======================= Finding good asso_values ======================== */ + +/* Initializes the asso_values[] related parameters. */ + +void +Search::prepare_asso_values () +{ + KeywordExt_List *temp; + + /* Initialize each keyword's _selchars array. */ + init_selchars_multiset(_key_positions, _alpha_unify, _alpha_inc); + + /* Compute the maximum _selchars_length over all keywords. */ + _max_selchars_length = _key_positions.iterator(_max_key_len).remaining(); + + /* Check for duplicates, i.e. keywords with the same _selchars array + (and - if !option[NOLENGTH] - also the same length). + We deal with these by building an equivalence class, so that only + 1 keyword is representative of the entire collection. Only this + representative remains in the keyword list; the others are accessible + through the _duplicate_link chain, starting at the representative. + This *greatly* simplifies processing during later stages of the program. + Set _total_duplicates and _list_len = _total_keys - _total_duplicates. */ + { + _list_len = _total_keys; + _total_duplicates = 0; + /* Make hash table for efficiency. */ + Hash_Table representatives (_list_len, option[NOLENGTH]); + + KeywordExt_List *prev = NULL; /* list node before temp */ + for (temp = _head; temp; ) + { + KeywordExt *keyword = temp->first(); + KeywordExt *other_keyword = representatives.insert (keyword); + KeywordExt_List *garbage = NULL; + + if (other_keyword) + { + _total_duplicates++; + _list_len--; + /* Remove keyword from the main list. */ + prev->rest() = temp->rest(); + garbage = temp; + /* And insert it on other_keyword's duplicate list. */ + keyword->_duplicate_link = other_keyword->_duplicate_link; + other_keyword->_duplicate_link = keyword; + + /* Complain if user hasn't enabled the duplicate option. */ + if (!option[DUP] || option[DEBUG]) + { + fprintf (stderr, "Key link: \"%.*s\" = \"%.*s\", with key set \"", + keyword->_allchars_length, keyword->_allchars, + other_keyword->_allchars_length, other_keyword->_allchars); + for (int j = 0; j < keyword->_selchars_length; j++) + putc (keyword->_selchars[j], stderr); + fprintf (stderr, "\".\n"); + } + } + else + { + keyword->_duplicate_link = NULL; + prev = temp; + } + temp = temp->rest(); + if (garbage) + delete garbage; + } + if (option[DEBUG]) + representatives.dump(); + } + + /* Exit program if duplicates exists and option[DUP] not set, since we + don't want to continue in this case. (We don't want to turn on + option[DUP] implicitly, because the generated code is usually much + slower. */ + if (_total_duplicates) + { + if (option[DUP]) + fprintf (stderr, "%d input keys have identical hash values, examine output carefully...\n", + _total_duplicates); + else + { + fprintf (stderr, "%d input keys have identical hash values,\n", + _total_duplicates); + if (option[POSITIONS]) + fprintf (stderr, "try different key positions or use option -D.\n"); + else + fprintf (stderr, "use option -D.\n"); + exit (1); + } + } + + /* Compute the occurrences of each character in the alphabet. */ + _occurrences = new int[_alpha_size]; + memset (_occurrences, 0, _alpha_size * sizeof (_occurrences[0])); + for (temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + const unsigned int *ptr = keyword->_selchars; + for (int count = keyword->_selchars_length; count > 0; ptr++, count--) + _occurrences[*ptr]++; + } + + /* Memory allocation. */ + _asso_values = new int[_alpha_size]; + + int non_linked_length = _list_len; + unsigned int asso_value_max; + + asso_value_max = + static_cast(non_linked_length * option.get_size_multiple()); + /* Round up to the next power of two. This makes it easy to ensure + an _asso_value[c] is >= 0 and < asso_value_max. Also, the jump value + being odd, it guarantees that Search::try_asso_value() will iterate + through different values for _asso_value[c]. */ + if (asso_value_max == 0) + asso_value_max = 1; + asso_value_max |= asso_value_max >> 1; + asso_value_max |= asso_value_max >> 2; + asso_value_max |= asso_value_max >> 4; + asso_value_max |= asso_value_max >> 8; + asso_value_max |= asso_value_max >> 16; + asso_value_max++; + _asso_value_max = asso_value_max; + + /* Given the bound for _asso_values[c], we have a bound for the possible + hash values, as computed in compute_hash(). */ + _max_hash_value = (option[NOLENGTH] ? 0 : _max_key_len) + + (_asso_value_max - 1) * _max_selchars_length; + /* Allocate a sparse bit vector for detection of collisions of hash + values. */ + _collision_detector = new Bool_Array (_max_hash_value + 1); + + if (option[DEBUG]) + { + fprintf (stderr, "total non-linked keys = %d\nmaximum associated value is %d" + "\nmaximum size of generated hash table is %d\n", + non_linked_length, asso_value_max, _max_hash_value); + + int field_width; + + field_width = 0; + { + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + if (field_width < keyword->_selchars_length) + field_width = keyword->_selchars_length; + } + } + + fprintf (stderr, "\ndumping the keyword list without duplicates\n"); + fprintf (stderr, "keyword #, %*s, keyword\n", field_width, "keysig"); + int i = 0; + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + fprintf (stderr, "%9d, ", ++i); + if (field_width > keyword->_selchars_length) + fprintf (stderr, "%*s", field_width - keyword->_selchars_length, ""); + for (int j = 0; j < keyword->_selchars_length; j++) + putc (keyword->_selchars[j], stderr); + fprintf (stderr, ", %.*s\n", + keyword->_allchars_length, keyword->_allchars); + } + fprintf (stderr, "\nend of keyword list\n\n"); + } + + if (option[RANDOM] || option.get_jump () == 0) + /* We will use rand(), so initialize the random number generator. */ + srand (static_cast(time (0))); + + _initial_asso_value = (option[RANDOM] ? -1 : option.get_initial_asso_value ()); + _jump = option.get_jump (); +} + +/* Finds some _asso_values[] that fit. */ + +/* The idea is to choose the _asso_values[] one by one, in a way that + a choice that has been made never needs to be undone later. This + means that we split the work into several steps. Each step chooses + one or more _asso_values[c]. The result of choosing one or more + _asso_values[c] is that the partitioning of the keyword set gets + broader. + Look at this partitioning: After every step, the _asso_values[] of a + certain set C of characters are undetermined. (At the beginning, C + is the set of characters c with _occurrences[c] > 0. At the end, C + is empty.) To each keyword K, we associate the multiset of _selchars + for which the _asso_values[] are undetermined: + K --> K->_selchars intersect C. + Consider two keywords equivalent if their value under this mapping is + the same. This introduces an equivalence relation on the set of + keywords. The equivalence classes partition the keyword set. (At the + beginning, the partition is the finest possible: each K is an equivalence + class by itself, because all K have a different _selchars. At the end, + all K have been merged into a single equivalence class.) + The partition before a step is always a refinement of the partition + after the step. + We choose the steps in such a way that the partition really becomes + broader at each step. (A step that only chooses an _asso_values[c] + without changing the partition is better merged with the previous step, + to avoid useless backtracking.) */ + +struct EquivalenceClass +{ + /* The keywords in this equivalence class. */ + KeywordExt_List * _keywords; + KeywordExt_List * _keywords_last; + /* The number of keywords in this equivalence class. */ + unsigned int _cardinality; + /* The undetermined selected characters for the keywords in this + equivalence class, as a canonically reordered multiset. */ + unsigned int * _undetermined_chars; + unsigned int _undetermined_chars_length; + + EquivalenceClass * _next; +}; + +struct Step +{ + /* The characters whose values are being determined in this step. */ + unsigned int _changing_count; + unsigned int * _changing; + /* Exclusive upper bound for the _asso_values[c] of this step. + A power of 2. */ + unsigned int _asso_value_max; + /* The characters whose values will be determined after this step. */ + bool * _undetermined; + /* The keyword set partition after this step. */ + EquivalenceClass * _partition; + /* The expected number of iterations in this step. */ + double _expected_lower; + double _expected_upper; + + Step * _next; +}; + +static inline bool +equals (const unsigned int *ptr1, const unsigned int *ptr2, unsigned int len) +{ + while (len > 0) + { + if (*ptr1 != *ptr2) + return false; + ptr1++; + ptr2++; + len--; + } + return true; +} + +EquivalenceClass * +Search::compute_partition (bool *undetermined) const +{ + EquivalenceClass *partition = NULL; + EquivalenceClass *partition_last = NULL; + for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + /* Compute the undetermined characters for this keyword. */ + unsigned int *undetermined_chars = + new unsigned int[keyword->_selchars_length]; + unsigned int undetermined_chars_length = 0; + + for (int i = 0; i < keyword->_selchars_length; i++) + if (undetermined[keyword->_selchars[i]]) + undetermined_chars[undetermined_chars_length++] = keyword->_selchars[i]; + + /* Look up the equivalence class to which this keyword belongs. */ + EquivalenceClass *equclass; + for (equclass = partition; equclass; equclass = equclass->_next) + if (equclass->_undetermined_chars_length == undetermined_chars_length + && equals (equclass->_undetermined_chars, undetermined_chars, + undetermined_chars_length)) + break; + if (equclass == NULL) + { + equclass = new EquivalenceClass(); + equclass->_keywords = NULL; + equclass->_keywords_last = NULL; + equclass->_cardinality = 0; + equclass->_undetermined_chars = undetermined_chars; + equclass->_undetermined_chars_length = undetermined_chars_length; + equclass->_next = NULL; + if (partition) + partition_last->_next = equclass; + else + partition = equclass; + partition_last = equclass; + } + else + delete[] undetermined_chars; + + /* Add the keyword to the equivalence class. */ + KeywordExt_List *cons = new KeywordExt_List(keyword); + if (equclass->_keywords) + equclass->_keywords_last->rest() = cons; + else + equclass->_keywords = cons; + equclass->_keywords_last = cons; + equclass->_cardinality++; + } + + /* Free some of the allocated memory. The caller doesn't need it. */ + for (EquivalenceClass *cls = partition; cls; cls = cls->_next) + delete[] cls->_undetermined_chars; + + return partition; +} + +static void +delete_partition (EquivalenceClass *partition) +{ + while (partition != NULL) + { + EquivalenceClass *equclass = partition; + partition = equclass->_next; + delete_list (equclass->_keywords); + //delete[] equclass->_undetermined_chars; // already freed above + delete equclass; + } +} + +/* Compute the possible number of collisions when _asso_values[c] is + chosen, leading to the given partition. */ +unsigned int +Search::count_possible_collisions (EquivalenceClass *partition, unsigned int c) const +{ + /* Every equivalence class p is split according to the frequency of + occurrence of c, leading to equivalence classes p1, p2, ... + This leads to (|p|^2 - |p1|^2 - |p2|^2 - ...)/2 possible collisions. + Return the sum of this expression over all equivalence classes. */ + unsigned int sum = 0; + unsigned int m = _max_selchars_length; + DYNAMIC_ARRAY (split_cardinalities, unsigned int, m + 1); + for (EquivalenceClass *cls = partition; cls; cls = cls->_next) + { + for (unsigned int i = 0; i <= m; i++) + split_cardinalities[i] = 0; + + for (KeywordExt_List *temp = cls->_keywords; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + unsigned int count = 0; + for (int i = 0; i < keyword->_selchars_length; i++) + if (keyword->_selchars[i] == c) + count++; + + split_cardinalities[count]++; + } + + sum += cls->_cardinality * cls->_cardinality; + for (unsigned int i = 0; i <= m; i++) + sum -= split_cardinalities[i] * split_cardinalities[i]; + } + FREE_DYNAMIC_ARRAY (split_cardinalities); + return sum; +} + +/* Test whether adding c to the undetermined characters changes the given + partition. */ +bool +Search::unchanged_partition (EquivalenceClass *partition, unsigned int c) const +{ + for (EquivalenceClass *cls = partition; cls; cls = cls->_next) + { + unsigned int first_count = UINT_MAX; + + for (KeywordExt_List *temp = cls->_keywords; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + + unsigned int count = 0; + for (int i = 0; i < keyword->_selchars_length; i++) + if (keyword->_selchars[i] == c) + count++; + + if (temp == cls->_keywords) + first_count = count; + else if (count != first_count) + /* c would split this equivalence class. */ + return false; + } + } + return true; +} + +void +Search::find_asso_values () +{ + Step *steps; + + /* Determine the steps, starting with the last one. */ + { + bool *undetermined; + bool *determined; + + steps = NULL; + + undetermined = new bool[_alpha_size]; + for (unsigned int c = 0; c < _alpha_size; c++) + undetermined[c] = false; + + determined = new bool[_alpha_size]; + for (unsigned int c = 0; c < _alpha_size; c++) + determined[c] = true; + + for (;;) + { + /* Compute the partition that needs to be refined. */ + EquivalenceClass *partition = compute_partition (undetermined); + + /* Determine the main character to be chosen in this step. + Choosing such a character c has the effect of splitting every + equivalence class (according the the frequency of occurrence of c). + We choose the c with the minimum number of possible collisions, + so that characters which lead to a large number of collisions get + handled early during the search. */ + unsigned int chosen_c; + unsigned int chosen_possible_collisions; + { + unsigned int best_c = 0; + unsigned int best_possible_collisions = UINT_MAX; + for (unsigned int c = 0; c < _alpha_size; c++) + if (_occurrences[c] > 0 && determined[c]) + { + unsigned int possible_collisions = + count_possible_collisions (partition, c); + if (possible_collisions < best_possible_collisions) + { + best_c = c; + best_possible_collisions = possible_collisions; + } + } + if (best_possible_collisions == UINT_MAX) + { + /* All c with _occurrences[c] > 0 are undetermined. We are + are the starting situation and don't need any more step. */ + delete_partition (partition); + break; + } + chosen_c = best_c; + chosen_possible_collisions = best_possible_collisions; + } + + /* We need one more step. */ + Step *step = new Step(); + + step->_undetermined = new bool[_alpha_size]; + memcpy (step->_undetermined, undetermined, _alpha_size*sizeof(bool)); + + step->_partition = partition; + + /* Now determine how the equivalence classes will be before this + step. */ + undetermined[chosen_c] = true; + partition = compute_partition (undetermined); + + /* Now determine which other characters should be determined in this + step, because they will not change the equivalence classes at + this point. It is the set of all c which, for all equivalence + classes, have the same frequency of occurrence in every keyword + of the equivalence class. */ + for (unsigned int c = 0; c < _alpha_size; c++) + if (_occurrences[c] > 0 && determined[c] + && unchanged_partition (partition, c)) + { + undetermined[c] = true; + determined[c] = false; + } + + /* main_c must be one of these. */ + if (determined[chosen_c]) + abort (); + + /* Now the set of changing characters of this step. */ + unsigned int changing_count; + + changing_count = 0; + for (unsigned int c = 0; c < _alpha_size; c++) + if (undetermined[c] && !step->_undetermined[c]) + changing_count++; + + unsigned int *changing = new unsigned int[changing_count]; + changing_count = 0; + for (unsigned int c = 0; c < _alpha_size; c++) + if (undetermined[c] && !step->_undetermined[c]) + changing[changing_count++] = c; + + step->_changing = changing; + step->_changing_count = changing_count; + + step->_asso_value_max = _asso_value_max; + + step->_expected_lower = + exp (static_cast(chosen_possible_collisions) + / static_cast(_max_hash_value)); + step->_expected_upper = + exp (static_cast(chosen_possible_collisions) + / static_cast(_asso_value_max)); + + delete_partition (partition); + + step->_next = steps; + steps = step; + } + + delete[] determined; + delete[] undetermined; + } + + if (option[DEBUG]) + { + unsigned int stepno = 0; + for (Step *step = steps; step; step = step->_next) + { + stepno++; + fprintf (stderr, "Step %u chooses _asso_values[", stepno); + for (unsigned int i = 0; i < step->_changing_count; i++) + { + if (i > 0) + fprintf (stderr, ","); + fprintf (stderr, "'%c'", step->_changing[i]); + } + fprintf (stderr, "], expected number of iterations between %g and %g.\n", + step->_expected_lower, step->_expected_upper); + fprintf (stderr, "Keyword equivalence classes:\n"); + for (EquivalenceClass *cls = step->_partition; cls; cls = cls->_next) + { + fprintf (stderr, "\n"); + for (KeywordExt_List *temp = cls->_keywords; temp; temp = temp->rest()) + { + KeywordExt *keyword = temp->first(); + fprintf (stderr, " %.*s\n", + keyword->_allchars_length, keyword->_allchars); + } + } + fprintf (stderr, "\n"); + } + } + + /* Initialize _asso_values[]. (The value given here matters only + for those c which occur in all keywords with equal multiplicity.) */ + for (unsigned int c = 0; c < _alpha_size; c++) + _asso_values[c] = 0; + + unsigned int stepno = 0; + for (Step *step = steps; step; step = step->_next) + { + stepno++; + + /* Initialize the asso_values[]. */ + unsigned int k = step->_changing_count; + for (unsigned int i = 0; i < k; i++) + { + unsigned int c = step->_changing[i]; + _asso_values[c] = + (_initial_asso_value < 0 ? rand () : _initial_asso_value) + & (step->_asso_value_max - 1); + } + + unsigned int iterations = 0; + DYNAMIC_ARRAY (iter, unsigned int, k); + for (unsigned int i = 0; i < k; i++) + iter[i] = 0; + unsigned int ii = (_jump != 0 ? k - 1 : 0); + + for (;;) + { + /* Test whether these asso_values[] lead to collisions among + the equivalence classes that should be collision-free. */ + bool has_collision = false; + for (EquivalenceClass *cls = step->_partition; cls; cls = cls->_next) + { + /* Iteration Number array is a win, O(1) initialization time! */ + _collision_detector->clear (); + + for (KeywordExt_List *ptr = cls->_keywords; ptr; ptr = ptr->rest()) + { + KeywordExt *keyword = ptr->first(); + + /* Compute the new hash code for the keyword, leaving apart + the yet undetermined asso_values[]. */ + int hashcode; + { + int sum = option[NOLENGTH] ? 0 : keyword->_allchars_length; + const unsigned int *p = keyword->_selchars; + int i = keyword->_selchars_length; + for (; i > 0; p++, i--) + if (!step->_undetermined[*p]) + sum += _asso_values[*p]; + hashcode = sum; + } + + /* See whether it collides with another keyword's hash code, + from the same equivalence class. */ + if (_collision_detector->set_bit (hashcode)) + { + has_collision = true; + break; + } + } + + /* Don't need to continue looking at the other equivalence + classes if we already have found a collision. */ + if (has_collision) + break; + } + + iterations++; + if (!has_collision) + break; + + /* Try other asso_values[]. */ + if (_jump != 0) + { + /* The way we try various values for + asso_values[step->_changing[0],...step->_changing[k-1]] + is like this: + for (bound = 0,1,...) + for (ii = 0,...,k-1) + iter[ii] := bound + iter[0..ii-1] := values <= bound + iter[ii+1..k-1] := values < bound + and + asso_values[step->_changing[i]] = + _initial_asso_value + iter[i] * _jump. + This makes it more likely to find small asso_values[]. + */ + unsigned int bound = iter[ii]; + unsigned int i = 0; + while (i < ii) + { + unsigned int c = step->_changing[i]; + iter[i]++; + _asso_values[c] = + (_asso_values[c] + _jump) & (step->_asso_value_max - 1); + if (iter[i] <= bound) + goto found_next; + _asso_values[c] = + (_asso_values[c] - iter[i] * _jump) + & (step->_asso_value_max - 1); + iter[i] = 0; + i++; + } + i = ii + 1; + while (i < k) + { + unsigned int c = step->_changing[i]; + iter[i]++; + _asso_values[c] = + (_asso_values[c] + _jump) & (step->_asso_value_max - 1); + if (iter[i] < bound) + goto found_next; + _asso_values[c] = + (_asso_values[c] - iter[i] * _jump) + & (step->_asso_value_max - 1); + iter[i] = 0; + i++; + } + /* Switch from one ii to the next. */ + { + unsigned int c = step->_changing[ii]; + _asso_values[c] = + (_asso_values[c] - bound * _jump) + & (step->_asso_value_max - 1); + iter[ii] = 0; + } + /* Here all iter[i] == 0. */ + ii++; + if (ii == k) + { + ii = 0; + bound++; + if (bound == step->_asso_value_max) + { + /* Out of search space! We can either backtrack, or + increase the available search space of this step. + It seems simpler to choose the latter solution. */ + step->_asso_value_max = 2 * step->_asso_value_max; + if (step->_asso_value_max > _asso_value_max) + { + _asso_value_max = step->_asso_value_max; + /* Reinitialize _max_hash_value. */ + _max_hash_value = + (option[NOLENGTH] ? 0 : _max_key_len) + + (_asso_value_max - 1) * _max_selchars_length; + /* Reinitialize _collision_detector. */ + delete _collision_detector; + _collision_detector = + new Bool_Array (_max_hash_value + 1); + } + } + } + { + unsigned int c = step->_changing[ii]; + iter[ii] = bound; + _asso_values[c] = + (_asso_values[c] + bound * _jump) + & (step->_asso_value_max - 1); + } + found_next: ; + } + else + { + /* Random. */ + unsigned int c = step->_changing[ii]; + _asso_values[c] = + (_asso_values[c] + rand ()) & (step->_asso_value_max - 1); + /* Next time, change the next c. */ + ii++; + if (ii == k) + ii = 0; + } + } + FREE_DYNAMIC_ARRAY (iter); + + if (option[DEBUG]) + { + fprintf (stderr, "Step %u chose _asso_values[", stepno); + for (unsigned int i = 0; i < step->_changing_count; i++) + { + if (i > 0) + fprintf (stderr, ","); + fprintf (stderr, "'%c'", step->_changing[i]); + } + fprintf (stderr, "] in %u iterations.\n", iterations); + } + } + + /* Free allocated memory. */ + while (steps != NULL) + { + Step *step = steps; + steps = step->_next; + delete[] step->_changing; + delete[] step->_undetermined; + delete_partition (step->_partition); + delete step; + } +} + +/* Computes a keyword's hash value, relative to the current _asso_values[], + and stores it in keyword->_hash_value. */ + +inline int +Search::compute_hash (KeywordExt *keyword) const +{ + int sum = option[NOLENGTH] ? 0 : keyword->_allchars_length; + + const unsigned int *p = keyword->_selchars; + int i = keyword->_selchars_length; + for (; i > 0; p++, i--) + sum += _asso_values[*p]; + + return keyword->_hash_value = sum; +} + +/* Finds good _asso_values[]. */ + +void +Search::find_good_asso_values () +{ + prepare_asso_values (); + + /* Search for good _asso_values[]. */ + int asso_iteration; + if ((asso_iteration = option.get_asso_iterations ()) == 0) + /* Try only the given _initial_asso_value and _jump. */ + find_asso_values (); + else + { + /* Try different pairs of _initial_asso_value and _jump, in the + following order: + (0, 1) + (1, 1) + (2, 1) (0, 3) + (3, 1) (1, 3) + (4, 1) (2, 3) (0, 5) + (5, 1) (3, 3) (1, 5) + ..... */ + KeywordExt_List *saved_head = _head; + int best_initial_asso_value = 0; + int best_jump = 1; + int *best_asso_values = new int[_alpha_size]; + int best_collisions = INT_MAX; + int best_max_hash_value = INT_MAX; + + _initial_asso_value = 0; _jump = 1; + for (;;) + { + /* Restore the keyword list in its original order. */ + _head = copy_list (saved_head); + /* Find good _asso_values[]. */ + find_asso_values (); + /* Test whether it is the best solution so far. */ + int collisions = 0; + int max_hash_value = INT_MIN; + _collision_detector->clear (); + for (KeywordExt_List *ptr = _head; ptr; ptr = ptr->rest()) + { + KeywordExt *keyword = ptr->first(); + int hashcode = compute_hash (keyword); + if (max_hash_value < hashcode) + max_hash_value = hashcode; + if (_collision_detector->set_bit (hashcode)) + collisions++; + } + if (collisions < best_collisions + || (collisions == best_collisions + && max_hash_value < best_max_hash_value)) + { + memcpy (best_asso_values, _asso_values, + _alpha_size * sizeof (_asso_values[0])); + best_collisions = collisions; + best_max_hash_value = max_hash_value; + } + /* Delete the copied keyword list. */ + delete_list (_head); + + if (--asso_iteration == 0) + break; + /* Prepare for next iteration. */ + if (_initial_asso_value >= 2) + _initial_asso_value -= 2, _jump += 2; + else + _initial_asso_value += _jump, _jump = 1; + } + _head = saved_head; + /* Install the best found asso_values. */ + _initial_asso_value = best_initial_asso_value; + _jump = best_jump; + memcpy (_asso_values, best_asso_values, + _alpha_size * sizeof (_asso_values[0])); + delete[] best_asso_values; + /* The keywords' _hash_value fields are recomputed below. */ + } +} + +/* ========================================================================= */ + +/* Comparison function for sorting by increasing _hash_value. */ +static bool +less_by_hash_value (KeywordExt *keyword1, KeywordExt *keyword2) +{ + return keyword1->_hash_value < keyword2->_hash_value; +} + +/* Sorts the keyword list by hash value. */ + +void +Search::sort () +{ + _head = mergesort_list (_head, less_by_hash_value); +} + +void +Search::optimize () +{ + /* Preparations. */ + prepare (); + + /* Step 1: Finding good byte positions. */ + find_positions (); + + /* Step 2: Finding good alpha increments. */ + find_alpha_inc (); + + /* Step 3: Finding good asso_values. */ + find_good_asso_values (); + + /* Make one final check, just to make sure nothing weird happened.... */ + _collision_detector->clear (); + for (KeywordExt_List *curr_ptr = _head; curr_ptr; curr_ptr = curr_ptr->rest()) + { + KeywordExt *curr = curr_ptr->first(); + unsigned int hashcode = compute_hash (curr); + if (_collision_detector->set_bit (hashcode)) + { + /* This shouldn't happen. proj1, proj2, proj3 must have been + computed to be injective on the given keyword set. */ + fprintf (stderr, + "\nInternal error, unexpected duplicate hash code\n"); + if (option[POSITIONS]) + fprintf (stderr, "try options -m or -r, or use new key positions.\n\n"); + else + fprintf (stderr, "try options -m or -r.\n\n"); + exit (1); + } + } + + /* Sorts the keyword list by hash value. */ + sort (); + + /* Set unused asso_values[c] to max_hash_value + 1. This is not absolutely + necessary, but speeds up the lookup function in many cases of lookup + failure: no string comparison is needed once the hash value of a string + is larger than the hash value of any keyword. */ + int max_hash_value; + { + KeywordExt_List *temp; + for (temp = _head; temp->rest(); temp = temp->rest()) + ; + max_hash_value = temp->first()->_hash_value; + } + for (unsigned int c = 0; c < _alpha_size; c++) + if (_occurrences[c] == 0) + _asso_values[c] = max_hash_value + 1; + + /* Propagate unified asso_values. */ + if (_alpha_unify) + for (unsigned int c = 0; c < _alpha_size; c++) + if (_alpha_unify[c] != c) + _asso_values[c] = _asso_values[_alpha_unify[c]]; +} + +/* Prints out some diagnostics upon completion. */ + +Search::~Search () +{ + delete _collision_detector; + if (option[DEBUG]) + { + fprintf (stderr, "\ndumping occurrence and associated values tables\n"); + + for (unsigned int i = 0; i < _alpha_size; i++) + if (_occurrences[i]) + fprintf (stderr, "asso_values[%c] = %6d, occurrences[%c] = %6d\n", + i, _asso_values[i], i, _occurrences[i]); + + fprintf (stderr, "end table dumping\n"); + + fprintf (stderr, "\nDumping key list information:\ntotal non-static linked keywords = %d" + "\ntotal keywords = %d\ntotal duplicates = %d\nmaximum key length = %d\n", + _list_len, _total_keys, _total_duplicates, _max_key_len); + + int field_width = _max_selchars_length; + fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n", + field_width, "selchars"); + for (KeywordExt_List *ptr = _head; ptr; ptr = ptr->rest()) + { + fprintf (stderr, "%11d,%11d,%6d, ", + ptr->first()->_hash_value, ptr->first()->_allchars_length, ptr->first()->_final_index); + if (field_width > ptr->first()->_selchars_length) + fprintf (stderr, "%*s", field_width - ptr->first()->_selchars_length, ""); + for (int j = 0; j < ptr->first()->_selchars_length; j++) + putc (ptr->first()->_selchars[j], stderr); + fprintf (stderr, ", %.*s\n", + ptr->first()->_allchars_length, ptr->first()->_allchars); + } + + fprintf (stderr, "End dumping list.\n\n"); + } + delete[] _asso_values; + delete[] _occurrences; + delete[] _alpha_unify; + delete[] _alpha_inc; +} diff --git a/contrib/gperf-3.0.1/src/search.h b/contrib/gperf-3.0.1/src/search.h new file mode 100644 index 0000000000..c098f509c5 --- /dev/null +++ b/contrib/gperf-3.0.1/src/search.h @@ -0,0 +1,165 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Search algorithm. + + Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef search_h +#define search_h 1 + +#include "keyword-list.h" +#include "positions.h" +#include "bool-array.h" + +struct EquivalenceClass; + +class Search +{ +public: + Search (KeywordExt_List *list); + ~Search (); + void optimize (); +private: + void prepare (); + + /* Computes the upper bound on the indices passed to asso_values[], + assuming no alpha_increments. */ + unsigned int compute_alpha_size () const; + + /* Computes the unification rules between different asso_values[c], + assuming no alpha_increments. */ + unsigned int * compute_alpha_unify () const; + + /* Initializes each keyword's _selchars array. */ + void init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify) const; + /* Deletes each keyword's _selchars array. */ + void delete_selchars () const; + + /* Count the duplicate keywords that occur with a given set of positions. */ + unsigned int count_duplicates_tuple (const Positions& positions, const unsigned int *alpha_unify) const; + + /* Find good key positions. */ + void find_positions (); + + /* Count the duplicate keywords that occur with the found set of positions. */ + unsigned int count_duplicates_tuple () const; + + /* Computes the upper bound on the indices passed to asso_values[]. */ + unsigned int compute_alpha_size (const unsigned int *alpha_inc) const; + + /* Computes the unification rules between different asso_values[c]. */ + unsigned int * compute_alpha_unify (const Positions& positions, const unsigned int *alpha_inc) const; + + /* Initializes each keyword's _selchars array. */ + void init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc) const; + + /* Count the duplicate keywords that occur with the given set of positions + and a given alpha_inc[] array. */ + unsigned int count_duplicates_multiset (const unsigned int *alpha_inc) const; + + /* Find good _alpha_inc[]. */ + void find_alpha_inc (); + + /* Initializes the asso_values[] related parameters. */ + void prepare_asso_values (); + + EquivalenceClass * compute_partition (bool *undetermined) const; + + unsigned int count_possible_collisions (EquivalenceClass *partition, unsigned int c) const; + + bool unchanged_partition (EquivalenceClass *partition, unsigned int c) const; + + /* Finds some _asso_values[] that fit. */ + void find_asso_values (); + + /* Computes a keyword's hash value, relative to the current _asso_values[], + and stores it in keyword->_hash_value. */ + int compute_hash (KeywordExt *keyword) const; + + /* Finds good _asso_values[]. */ + void find_good_asso_values (); + + /* Sorts the keyword list by hash value. */ + void sort (); + +public: + + /* Linked list of keywords. */ + KeywordExt_List * _head; + + /* Total number of keywords, counting duplicates. */ + int _total_keys; + + /* Maximum length of the longest keyword. */ + int _max_key_len; + + /* Minimum length of the shortest keyword. */ + int _min_key_len; + + /* User-specified or computed key positions. */ + Positions _key_positions; + + /* Adjustments to add to bytes add specific key positions. */ + unsigned int * _alpha_inc; + + /* Size of alphabet. */ + unsigned int _alpha_size; + + /* Alphabet character unification, either the identity or a mapping from + upper case characters to lower case characters (and maybe more). */ + unsigned int * _alpha_unify; + + /* Maximum _selchars_length over all keywords. */ + unsigned int _max_selchars_length; + + /* Total number of duplicates that have been moved to _duplicate_link lists + (not counting their representatives which stay on the main list). */ + int _total_duplicates; + + /* Counts occurrences of each key set character. + _occurrences[c] is the number of times that c occurs among the _selchars + of a keyword. */ + int * _occurrences; + /* Value associated with each character. */ + int * _asso_values; + +private: + + /* Length of _head list. Number of keywords, not counting duplicates. */ + int _list_len; + + /* Exclusive upper bound for every _asso_values[c]. A power of 2. */ + unsigned int _asso_value_max; + + /* Initial value for asso_values table. -1 means random. */ + int _initial_asso_value; + /* Jump length when trying alternative values. 0 means random. */ + int _jump; + + /* Maximal possible hash value. */ + int _max_hash_value; + + /* Sparse bit vector for collision detection. */ + Bool_Array * _collision_detector; +}; + +#endif diff --git a/contrib/gperf-3.0.1/src/version.cc b/contrib/gperf-3.0.1/src/version.cc new file mode 100644 index 0000000000..d9508c66c6 --- /dev/null +++ b/contrib/gperf-3.0.1/src/version.cc @@ -0,0 +1,28 @@ +/* Current program version number. + + Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Specification. */ +#include "version.h" + +/* Current release version. */ +const char *version_string = "3.0.1"; diff --git a/contrib/gperf-3.0.1/src/version.h b/contrib/gperf-3.0.1/src/version.h new file mode 100644 index 0000000000..3ba414d1ff --- /dev/null +++ b/contrib/gperf-3.0.1/src/version.h @@ -0,0 +1,25 @@ +/* Current program version number. + + Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc. + Written by Douglas C. Schmidt + and Bruno Haible . + + This file is part of GNU GPERF. + + GNU GPERF is free software; you can 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. + + GNU GPERF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Current release version. */ +extern const char *version_string; -- 2.41.0