From 501ee3e64033e900181aaebd7ae44dbcacccca9d Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 19 Aug 2000 06:20:11 +0000 Subject: [PATCH] Initial revision --- COPYING | 249 +++ ChangeLog | 1492 ++++++++++++++ INSTALL | 181 ++ Makefile.devel | 35 + Makefile.in | 62 + NEWS | 11 + README | 24 + acconfig.h | 4 + aclocal.m4 | 71 + configure | 909 +++++++++ configure.in | 46 + doc/Makefile.in | 129 ++ doc/configure | 863 ++++++++ doc/configure.in | 33 + doc/gperf.1 | 23 + doc/gperf.dvi | Bin 0 -> 67424 bytes doc/gperf.html | 1381 +++++++++++++ doc/gperf.info | 1202 +++++++++++ doc/gperf.ps | 2883 ++++++++++++++++++++++++++ doc/gperf.texi | 1251 ++++++++++++ doc/gperf_1.html | 25 + doc/gperf_10.html | 30 + doc/gperf_11.html | 82 + doc/gperf_2.html | 360 ++++ doc/gperf_3.html | 42 + doc/gperf_4.html | 44 + doc/gperf_5.html | 95 + doc/gperf_6.html | 292 +++ doc/gperf_7.html | 393 ++++ doc/gperf_8.html | 66 + doc/gperf_9.html | 54 + doc/gperf_toc.html | 50 + doc/texinfo.tex | 4585 ++++++++++++++++++++++++++++++++++++++++++ lib/Makefile.in | 109 + lib/configure | 1303 ++++++++++++ lib/configure.in | 43 + lib/getopt.c | 1042 ++++++++++ lib/getopt.c.patch | 25 + lib/getopt.h | 138 ++ lib/getopt.h.patch | 40 + lib/getopt1.c | 188 ++ lib/hash.cc | 36 + lib/hash.h | 27 + src/Makefile.in | 143 ++ src/bool-array.cc | 49 + src/bool-array.h | 66 + src/bool-array.icc | 85 + src/config.h.in | 19 + src/configure | 1573 +++++++++++++++ src/configure.in | 71 + src/gen-perf.cc | 342 ++++ src/gen-perf.h | 50 + src/hash-table.cc | 91 + src/hash-table.h | 42 + src/iterator.cc | 88 + src/iterator.h | 51 + src/key-list.cc | 1957 ++++++++++++++++++ src/key-list.h | 96 + src/list-node.cc | 101 + src/list-node.h | 45 + src/main.cc | 72 + src/new.cc | 87 + src/options.cc | 668 ++++++ src/options.h | 157 ++ src/options.icc | 175 ++ src/read-line.cc | 97 + src/read-line.h | 53 + src/read-line.icc | 47 + src/trace.cc | 35 + src/trace.h | 40 + src/vectors.cc | 25 + src/vectors.h | 37 + src/version.cc | 22 + src/version.h | 23 + tests/Makefile.in | 232 +++ tests/ada-pred.exp | 54 + tests/ada-res.exp | 63 + tests/ada.gperf | 63 + tests/adadefs.gperf | 54 + tests/c++.gperf | 47 + tests/c-parse.gperf | 56 + tests/c.exp | 32 + tests/c.gperf | 32 + tests/configure | 1214 +++++++++++ tests/configure.in | 45 + tests/gpc.gperf | 48 + tests/gplus.gperf | 76 + tests/irc.gperf | 63 + tests/jscript.gperf | 73 + tests/jstest1.gperf | 142 ++ tests/jstest2.gperf | 147 ++ tests/jstest3.gperf | 147 ++ tests/makeinfo.gperf | 116 ++ tests/modula.exp | 106 + tests/modula2.gperf | 40 + tests/modula3.gperf | 106 + tests/pascal.exp | 36 + tests/pascal.gperf | 36 + tests/test-1.exp | 153 ++ tests/test-2.exp | 202 ++ tests/test-3.exp | 186 ++ tests/test-4.exp | 162 ++ tests/test-5.exp | 124 ++ tests/test-6.exp | 119 ++ tests/test-7.exp | 32 + tests/test.c | 26 + tests/validate | 54 + 107 files changed, 30411 insertions(+) create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.devel create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 acconfig.h create mode 100644 aclocal.m4 create mode 100755 configure create mode 100644 configure.in create mode 100644 doc/Makefile.in create mode 100755 doc/configure create mode 100644 doc/configure.in create mode 100644 doc/gperf.1 create mode 100644 doc/gperf.dvi create mode 100644 doc/gperf.html create mode 100644 doc/gperf.info create mode 100644 doc/gperf.ps create mode 100644 doc/gperf.texi create mode 100644 doc/gperf_1.html create mode 100644 doc/gperf_10.html create mode 100644 doc/gperf_11.html create mode 100644 doc/gperf_2.html create mode 100644 doc/gperf_3.html create mode 100644 doc/gperf_4.html create mode 100644 doc/gperf_5.html create mode 100644 doc/gperf_6.html create mode 100644 doc/gperf_7.html create mode 100644 doc/gperf_8.html create mode 100644 doc/gperf_9.html create mode 100644 doc/gperf_toc.html create mode 100644 doc/texinfo.tex create mode 100644 lib/Makefile.in create mode 100755 lib/configure create mode 100644 lib/configure.in create mode 100644 lib/getopt.c create mode 100644 lib/getopt.c.patch create mode 100644 lib/getopt.h create mode 100644 lib/getopt.h.patch create mode 100644 lib/getopt1.c create mode 100644 lib/hash.cc create mode 100644 lib/hash.h create mode 100644 src/Makefile.in create mode 100644 src/bool-array.cc create mode 100644 src/bool-array.h create mode 100644 src/bool-array.icc create mode 100644 src/config.h.in create mode 100755 src/configure create mode 100644 src/configure.in create mode 100644 src/gen-perf.cc create mode 100644 src/gen-perf.h create mode 100644 src/hash-table.cc create mode 100644 src/hash-table.h create mode 100644 src/iterator.cc create mode 100644 src/iterator.h create mode 100644 src/key-list.cc create mode 100644 src/key-list.h create mode 100644 src/list-node.cc create mode 100644 src/list-node.h create mode 100644 src/main.cc create mode 100644 src/new.cc create mode 100644 src/options.cc create mode 100644 src/options.h create mode 100644 src/options.icc create mode 100644 src/read-line.cc create mode 100644 src/read-line.h create mode 100644 src/read-line.icc create mode 100644 src/trace.cc create mode 100644 src/trace.h create mode 100644 src/vectors.cc create mode 100644 src/vectors.h create mode 100644 src/version.cc create mode 100644 src/version.h create mode 100644 tests/Makefile.in create mode 100644 tests/ada-pred.exp create mode 100644 tests/ada-res.exp create mode 100644 tests/ada.gperf create mode 100644 tests/adadefs.gperf create mode 100644 tests/c++.gperf create mode 100644 tests/c-parse.gperf create mode 100644 tests/c.exp create mode 100644 tests/c.gperf create mode 100755 tests/configure create mode 100644 tests/configure.in create mode 100644 tests/gpc.gperf create mode 100644 tests/gplus.gperf create mode 100644 tests/irc.gperf create mode 100644 tests/jscript.gperf create mode 100644 tests/jstest1.gperf create mode 100644 tests/jstest2.gperf create mode 100644 tests/jstest3.gperf create mode 100644 tests/makeinfo.gperf create mode 100644 tests/modula.exp create mode 100644 tests/modula2.gperf create mode 100644 tests/modula3.gperf create mode 100644 tests/pascal.exp create mode 100644 tests/pascal.gperf create mode 100644 tests/test-1.exp create mode 100644 tests/test-2.exp create mode 100644 tests/test-3.exp create mode 100644 tests/test-4.exp create mode 100644 tests/test-5.exp create mode 100644 tests/test-6.exp create mode 100644 tests/test-7.exp create mode 100644 tests/test.c create mode 100755 tests/validate diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..9a17037 --- /dev/null +++ b/COPYING @@ -0,0 +1,249 @@ + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our 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. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, 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 a 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 tell them 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. + + 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 Agreement 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 work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 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 +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual 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 General + Public License. + + d) 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. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 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 + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying 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. + + 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. + + 7. 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 the 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 +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. 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 + + 9. 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. + + 10. 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 humanity, 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) 19yy + + 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 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx 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 a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..f224843 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1492 @@ +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/INSTALL b/INSTALL new file mode 100644 index 0000000..a2c8722 --- /dev/null +++ b/INSTALL @@ -0,0 +1,181 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source 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. + +`--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/Makefile.devel b/Makefile.devel new file mode 100644 index 0000000..e145bd8 --- /dev/null +++ b/Makefile.devel @@ -0,0 +1,35 @@ +# 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 + +CONFIGURES = configure lib/configure src/configure tests/configure doc/configure + +configures : $(CONFIGURES) + +configure : configure.in aclocal.m4 + autoconf -l . + +lib/configure : lib/configure.in aclocal.m4 + cd lib && autoconf -l .. + +src/configure : src/configure.in aclocal.m4 + cd src && autoconf -l .. + +tests/configure : tests/configure.in aclocal.m4 + cd tests && autoconf -l .. + +doc/configure : doc/configure.in aclocal.m4 + cd doc && autoconf -l .. + +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 -l .. + +force : + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..1d9336a --- /dev/null +++ b/Makefile.in @@ -0,0 +1,62 @@ +# Makefile for gperf + +# Copyright (C) 1989, 1992, 1993, 1998 Free Software Foundation, Inc. +# written by Douglas C. Schmidt (schmidt@ics.uci.edu) +# +# 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 1, 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 GNU GPERF; see the file COPYING. If not, write to +# Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#### Start of system configuration section. #### + +# Programs used by "make": +RM = rm -f +@SET_MAKE@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +all : force + cd @subdir@; $(MAKE) all + +install : force + cd @subdir@; $(MAKE) install + +installdirs : force + cd @subdir@; $(MAKE) installdirs + +uninstall : force + cd @subdir@; $(MAKE) uninstall + +check : force + cd @subdir@; $(MAKE) check + +mostlyclean : force + cd @subdir@; $(MAKE) mostlyclean + +clean : force + cd @subdir@; $(MAKE) clean + +distclean : force + cd @subdir@; if test -f Makefile; then $(MAKE) distclean; fi + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : force + cd @subdir@; if test -f Makefile; then $(MAKE) maintainer-clean; fi + $(RM) config.status config.log config.cache Makefile + +force : + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..28ddd4c --- /dev/null +++ b/NEWS @@ -0,0 +1,11 @@ +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/README b/README new file mode 100644 index 0000000..bd9d14e --- /dev/null +++ b/README @@ -0,0 +1,24 @@ +While teaching a data structures course at University of California, +Irvine, I developed a program called GPERF that generates perfect hash +functions for sets of key words. A perfect hash function is simply: + + 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 gperf.texinfo 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 word sets. The texinfo file is readable +both via the GNU emacs `info' command, and is also suitable for +typesetting with TeX. + +The enclosed Makefile creates the executable program ``gperf'' and +also runs some tests. + +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. + +Happy hacking! + +Douglas C. Schmidt diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..cd040d4 --- /dev/null +++ b/acconfig.h @@ -0,0 +1,4 @@ + +/* Define if the C++ compiler supports "throw ()" declarations. */ +#undef HAVE_THROW_DECL + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..b39197a --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,71 @@ +AC_PREREQ(2.12) + +AC_DEFUN(CL_PROG_RANLIB, [AC_CHECK_PROG(RANLIB, ranlib, ranlib, true)]) + +AC_DEFUN(CL_PROG_INSTALL, +[dnl This is mostly copied from AC_PROG_INSTALL. +# 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. +AC_MSG_CHECKING(for a BSD compatible install) +if test -z "$INSTALL"; then +AC_CACHE_VAL(cl_cv_path_install, +[ 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 + ac_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" +])dnl + INSTALL="$cl_cv_path_install" +fi +dnl We do special magic for INSTALL instead of AC_SUBST, to get +dnl relative paths right. +AC_MSG_RESULT($INSTALL) +AC_SUBST(INSTALL)dnl +# 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)' +AC_SUBST(INSTALL_PROGRAM)dnl +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi +AC_SUBST(INSTALL_DATA)dnl +]) + diff --git a/configure b/configure new file mode 100755 index 0000000..7ac6dd5 --- /dev/null +++ b/configure @@ -0,0 +1,909 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=doc/gperf.1 + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:523: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +extrasub="$extrasub"' +/@subdir@/{ +h +g +s/@subdir@/lib/ +p +g +s/@subdir@/src/ +p +g +s/@subdir@/tests/ +p +g +s/@subdir@/doc/ +p +d +} +' +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -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=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in lib src tests doc; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; } + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2 + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + ac_sub_cache_file="$ac_dots$cache_file" ;; + esac + + echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; } + fi + fi + + cd $ac_popdir + done +fi + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..5ac1499 --- /dev/null +++ b/configure.in @@ -0,0 +1,46 @@ +dnl autoconf configuration for gperf + +dnl Copyright (C) 1998 Free Software Foundation, Inc. +dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu) +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the +dnl Free Software Foundation, 59 Temple Place - Suite 330, Boston, +dnl MA 02111-1307, USA. + +AC_INIT(doc/gperf.1) +AC_PROG_MAKE_SET +dnl This piece of sed script replaces every line containing '@subdir@' +dnl by several consecutive lines, each referencing one subdir. +extrasub="$extrasub"' +/@subdir@/{ +h +g +s/@subdir@/lib/ +p +g +s/@subdir@/src/ +p +g +s/@subdir@/tests/ +p +g +s/@subdir@/doc/ +p +d +} +' +AC_OUTPUT(Makefile) +AC_OUTPUT_SUBDIRS(lib src tests doc) diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..bfacd16 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,129 @@ +# Makefile for gperf/doc + +# Copyright (C) 1998 Free Software Foundation, Inc. +# +# 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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +# Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ + +# Directories used by "make install": +prefix = @prefix@ +local_prefix = /usr/local +exec_prefix = @exec_prefix@ +infodir = @infodir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +dvidir = $(mandir)/dvi +htmldir = $(mandir)/html + +# Programs used by "make": +RM = rm -f +@SET_MAKE@ + +# Programs used by "make" if you have changed the documentation files: +TEX = tex +TEXI2DVI = texi2dvi +DVIPS = dvips -Pljfour +MAKEINFO = LANGUAGE= makeinfo +TEXI2HTML = texi2html + +# Programs used by "make install": +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +VPATH = $(srcdir) + +all : info dvi ps html + + +info : $(srcdir)/gperf.info + +$(srcdir)/gperf.info : $(srcdir)/gperf.texi + cd $(srcdir) && $(MAKEINFO) --no-split gperf.texi + + +dvi : $(srcdir)/gperf.dvi + +$(srcdir)/gperf.dvi : $(srcdir)/gperf.texi + cd $(srcdir) && $(RM) gperf.aux gperf.toc gperf.cp gperf.fn gperf.ky gperf.pg gperf.tp gperf.vr gperf.log + cd $(srcdir) && $(TEXI2DVI) gperf.texi + cd $(srcdir) && $(RM) gperf.aux gperf.toc gperf.cp gperf.fn gperf.ky gperf.pg gperf.tp gperf.vr gperf.log + + +ps : $(srcdir)/gperf.ps + +$(srcdir)/gperf.ps : $(srcdir)/gperf.dvi + $(DVIPS) -o $@ $< + + +html : gperf.html gperf_toc.html + +gperf.html : $(srcdir)/gperf.texi + cd $(srcdir) && $(TEXI2HTML) -expandinfo -number -monolithic gperf.texi + +gperf_toc.html : $(srcdir)/gperf.texi + cd $(srcdir) && $(RM) gperf_*.html + cd $(srcdir) && $(TEXI2HTML) -expandinfo -number -split_chapter gperf.texi + + +install : all force + if [ ! -d $(infodir) ] ; then mkdir $(infodir) ; fi + $(INSTALL_DATA) $(srcdir)/gperf.info $(infodir)/gperf.info + if [ ! -d $(mandir) ] ; then mkdir $(mandir) ; fi + if [ ! -d $(man1dir) ] ; then mkdir $(man1dir) ; fi + $(INSTALL_DATA) $(srcdir)/gperf.1 $(man1dir)/gperf.1 + if [ ! -d $(dvidir) ] ; then mkdir $(dvidir) ; fi + $(INSTALL_DATA) $(srcdir)/gperf.dvi $(dvidir)/gperf.dvi + if [ ! -d $(htmldir) ] ; then mkdir $(htmldir) ; fi + $(INSTALL_DATA) $(srcdir)/gperf.html $(htmldir)/gperf.html + +installdirs : force + if [ ! -d $(infodir) ] ; then mkdir $(infodir) ; fi + if [ ! -d $(mandir) ] ; then mkdir $(mandir) ; fi + if [ ! -d $(man1dir) ] ; then mkdir $(man1dir) ; fi + if [ ! -d $(dvidir) ] ; then mkdir $(dvidir) ; fi + if [ ! -d $(htmldir) ] ; then mkdir $(htmldir) ; fi + +uninstall : force + $(RM) $(infodir)/gperf.info + $(RM) $(man1dir)/gperf.1 + $(RM) $(dvidir)/gperf.dvi + $(RM) $(htmldir)/gperf.html + +check : all + +mostlyclean : clean + +clean : force + $(RM) *~ *.aux *.toc *.cp *.fn *.ky *.pg *.tp *.vr *.my *.log core + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + $(RM) *.info *.dvi *.ps *.html + +force : + diff --git a/doc/configure b/doc/configure new file mode 100755 index 0000000..7b6e3c3 --- /dev/null +++ b/doc/configure @@ -0,0 +1,863 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=gperf.1 + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:523: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:560: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'cl_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&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 + ac_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 "$ac_t""$INSTALL" 1>&6 +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='$(INSTALL)' +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi + + trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/doc/configure.in b/doc/configure.in new file mode 100644 index 0000000..f72482c --- /dev/null +++ b/doc/configure.in @@ -0,0 +1,33 @@ +dnl autoconf configuration for gperf/doc + +dnl Copyright (C) 1998 Free Software Foundation, Inc. +dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu) +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the +dnl Free Software Foundation, 59 Temple Place - Suite 330, Boston, +dnl MA 02111-1307, USA. + +AC_INIT(gperf.1) +AC_PROG_MAKE_SET +dnl +dnl checks for programs +dnl +CL_PROG_INSTALL + dnl sets variables INSTALL, INSTALL_DATA, INSTALL_PROGRAM +dnl +dnl That's it. +dnl +AC_OUTPUT(Makefile) diff --git a/doc/gperf.1 b/doc/gperf.1 new file mode 100644 index 0000000..1e4a2aa --- /dev/null +++ b/doc/gperf.1 @@ -0,0 +1,23 @@ +.TH GPERF 1 "March 7, 1998 +.UC 4 +.SH NAME +gperf \- generate a perfect hash function from a key set +.SH SYNOPSIS +.B gperf +[ +.B \-adghijklnoprsStv +] [ +.I keyfile +] +.SH DESCRIPTION + +\fIgperf\fP reads a set of ``keys'' from \fIkeyfile\fP (or, by +default, from the standard input) and attempts to find a non-minimal +perfect hashing function that recognizes a member of the key set in +constant, i.e., O(1), time. If such a function is found the program +generates a pair of \fIC\fP source code routines that perform the +hashing and table lookup. All generated code is directed to the +standard output. + +Please refer to the \fIgperf.texi\fP file for more information. +This file is distributed with \fIgperf\fP release. diff --git a/doc/gperf.dvi b/doc/gperf.dvi new file mode 100644 index 0000000000000000000000000000000000000000..cc1f0206a32021b94306c4521985af53ffc712e6 GIT binary patch literal 67424 zcmce<2Yg&tnfLE#MkyqL4WUBk*lybc`Q?EUx@7#0G>0NPF?~0Y@ z^{whV=Vd%`m>&B}fBwXu-Ftt&Xwjb6b-ifSeY;=x$CE$w?cKL5y5nZn$@%T+xqf zQ~5ow-`%)jrt6|jTbp`r^Wc_s(big_Sg1Ar^sFb%?%8{Zz4L+W@Ixyv`Po&oiyrpS zszncDmhQ3XO5ck1+H!ren5#B3w@(c8Mk8Z4zw@N2>B4wz&)y5{#kaoYcz#{e@9Q%+ zZ`?PYtL4X|zB8l#nM$D;i5h$Mp6J%~-5;?oJ-L%n@|9|#T#8oqp1o(!-p4Ik^m0+E z>n~Bs|Nit2O8u#C-%ob82g){n|3u_sA^-)uHU}6P>m)lxl&6MsgTa0%9X~W z@j|s$DQvIT^3l##zOtR6rlYa)Od(&5$`es-iZ`cuv7ReNGnH~{C#TC0Q+YkqvMsi1 zd+vM$la|W0!kDc}1KXQAhIk#3dq7KPs5~5F#2=5KeXdyav-ZL!oy*T``^|#o+tdq} zKV8%})dwCbBbxZs-f`POQEEA~y!)VTkv1kKyD^>H0qk%|(|h}d@lx{OD=TII?PW=b9XII|jM#8Nuj8i!`Y%S8t~ zLYSb0;Bek-0)Dc?E|>EAA71udKR%ShtHGSrqVe(mhgN{PWsbYd(kf9gSDLKnCi6Y< zqOmi{`o`A zzW3ek_?R~wU^6rM^@V3Ron!pjXuDXSLvv@T)5}GvT}HVXV=A4<_SUQ&ZLVIMVxfgn zwU*Bz78Cx=nJ}EXRL5XxvRJ52^`?~7A*pq=|EMXe-K-xa%up8%ZW`RuzaiSZbi>ZoY2$%MVu>ewe+EPF zj{kjs`%)<}CzzVMuP0j9%5SgKbCp??^Ev14+56=4w(V{_>4B|>pg$LAO4EgZg_1nx z`HO6()n}ijS2yOW)u`XZzb6{VO}DmJ3gfU?w6Q;0v9fQ~xjoU=k^VhT0ta`( zW_i{P&+C0yJjhASt5|fD@xfnEvNDPcSf0=@CPpX(DT8QS`fRK|oi8y?ttUc9M`Nui zxL@L2s7Zto38~I70SC3-4(j0(6X}C`aQ)^=J~w^y%RjTdnBTMK&Xe8` ztx?2kFeRk1rvBGo-so}S5-WFKk}0KvqR z5t`0d#vqRDN4W|bka>vT>uqG;{_Hig&CGG%L`1c@3TC^fkvStO*DKM1b)$AGJ&;F% zn+Zb)ID?jtW-)@5Xo7W*m#4L&>J$rwve3SnJ@wOL%ptnv?U~eGuIE{23afQ?CMA;E zC^KqIQy#KUg<93^vbS;gwxc22f~7K{SLDsEZ@&-uE*g=f9rMwFEjZ7uODy=3s!bo; zca0)TD&2>+g`kX7k;2E8Pe;2%+sG-6Dw9Lt>4L!@-l$g{mq6@x`-%pVSFT56xsrAu z=8;C6Wl&Mh4_NJCDtNBki^36WTsD<2H8bZNu?zY^8RPKW4jrq}B_S1Ox9JJ6pqchc zej;C~Xm*z252a_02gIx(v9UaBdf)LQHr!a@7)(fURtxNDiBSId*^g7K&1}zco~&lH z^3}p*$*}-O=T_zp58e|eL{qsIhR&#-;)zLFzbGdrM%}XeYCgssY>D~w@Lcxt$7)~U z3@{LX_aa#ay;E;h@?-e|=A~7IZe#h@m|>1Q7PSR!Ta)=(tHA$FxTisB*ld2XU=%$% z#xmhZZJDXlQ%VuAJe?CLY|P;>iF+w3<###KhZ8&BK#*CkSxCX=ca%^Djt)BQapOLQ zLba48tKnovjUk$uXMBc{YJix?y!E_pHI}c`a!`haiJw4oh3)bvBzeZ-Fa+}!Ouc#%r64a#ItIFF+3yj96eipzJg}UY zMQ#EC*BJrX%}Z|uqD{{f^HA*OQ}v2FhXYQMW2dNakbplxpb2ce zPTl8Jx0A$X=I-Y>UC^UB;Q5x#$-3Ywtt0Og4Qp_sfLVb4lQ`dI=KRm+bLPW(6^{1zyO&3yg`;DtJuRnwQCpmH zB8h?VO$hTGPsPcf!T4&8*Q@MKzinnO`x@)PzQJ6ja<|+tLgw*So;x?m7tkr|| z!_fVF_0WVLq0>0=BIBi;uI*-`s^#gt^gzCd;Ij%AF_WuS@n*6gp1?_MbRT|y$BtxG z(`<}7a5~I(w#$R^*`U>J56<}tnApY)UYQh;=B$)~Inx#_C^(E^{8=CKc-u^A6~2No zWtb}YW2FY6yksa09jxmTeosWj`6p@MeTY$l!w(CaBw{0M9=pmzFpv@a8P5m2Q-YKMj&JVi(9*QKe&E$aLdLK z7PPT{)7ofYc+=XU(V^i@BLMit7yWNS7TrJjZo98{Pvg<=7#}4j(9FEy*kG0WQ;1P+ zO@KW*ilFGE)f{?p?x(~KMaT|X(%)#W5FMB)<~Sn<88zE>^c`%v_=`Fhwisd#(Nwu8 zi&4d#JE(&?V?yV5CBiu#B|d-b)*8Ea0!^4k)A>!o`K2>Pr@#YG{pz;O4sb2*X=XRB zvhj;$n0=RYBUq;@#gHo@G_x)Ado3|1Ao0je5l&UH8!JJO3=sXisB)Rc%Y%ZHnXkwc*>*C%$cOD;jWu;>kZ*H2|Z@<{P z#dd&s zZmBSd4FLVBGlj8wxn5P21)(y(9GFV*ke|#bKvSKPUO-zL$HIYrx*YRde`D$e@u%28 z2qr@DUVkI11)_!hjumqST%!mC-JylgZ)Cssk{uCl)Ew_9&_mRxg+Vt%;>Li>(1m_x z-WZ#pM3$|egZSHQ`+7I3JA zsWOtxOhvO*1)o|XRC%IhkrnTE@GPrwW?H7#l-H_GhV0&Wzh}tUXd6d?Z=_-*XZ$6F z4by^UdQE6E$QHm5BlO;nI;E`l`J3NL!sgA)iZ1j6G@Od-S&z0 zSPmznnTby3;dn(z^f5&__hq171rMLOrVAw(h44xmKUKC+E}rbOlOzjG$XQ@88^P0n znfQ^Ejso&2{zIJP0+|nU;H7n+a=k{w(JiK5bS5O3Iw7&n&5JAt@^_2u8RW^2px9b8 zldG5*u`Z-v94!OX%zpC%&9&b-^R%{9$(JX3=DL?Z*K1B=Vy`kux5VW02Z}FScBV+@ z!Bk#%0)vjf9Fl><4Eu?qiP)EqA&A$?GkSNK6S)+d z0U*1+{{s;>m=?H%$z&oSL}i-I&tgh*<5h%inrs7qDaf883&^)nd2v=_;3?ti)j^S& zN4%!P!7x_#L@M&@MSg2K)Mn;MuQY}{AfD%!OId;7H&i-jN!6m!ouUfuO?#lWQ|G_T_G)Yc zA&BLPYy7+wjA+OcH8byeuMRVuV9cm676RpyDop;~qeVQqer|dra0T23Q|=Or?JN+_ z@TS90l!}8M*oN%KT`|OX;e7#OpjRYT=0V$W+j6H`&SXTel(bOVWQ0}tlYQT>v~p8x zCOTfnRl*{T(WTMMt?V%6`e{m#&^L%A3fRXVIT~9Q!27W`Jz$7)Bf6#86@4%_367q0 z@Z5~F!^;IMgSnyn*Lch$zlByb(y_~#vP4hgPvdJD3VVU?tJK5JR=G$lSvvp)Lgwty zk%S{^Wo(Sed3?Z&Lrbh4cWrQ){&KEj)xunb+?6vsEq>w$3$GK7_l!zR>3&htCBA}%N2HZL zOQY>3aAPOu;`V5ftF8mH5eamLz0M!2ZEc9xP8LwM-K~>sW7f*pWgZ7JkQ&6=W%bk z7=)Bk*SRqlsYgnQ(VzNTLXR=8={LnZR(z~X#LkD@#>E)ZLdU>_<Qvvc4eRxk(j*f#$KN}O*NsG_9c!FQ8=^4G&|P<@pGxf%|K&=3yV)6R9r zTO^t(6M@VZ^W-Jq3?%_(TlpN(7(FNJ>4M1uf*56QwPS6mI7+kY5C7t=u^SE{0!Cp% zTsA@qO4Eq%#*|@!p<;HF88wyUsl6X@y&^*3APc9o<2h1jHk6%<5}{~f&LuvD*0>D9 zuBWp4?MP`n7nU&*;e#=rpAYtveiH`@NnoKd&4)z!uJ7y#l-Du~C2_pdbsdhJxsxmr z4|m>wdAl$j8L`F@xqFw6s)iv~WN#&>5@k5S94>2yV1Pb! z6s2-W@PpJ>%IhF@GD(POAJ5dO(D-Z#m zHO!6I`KDV)YvQzDdlrQ~+2OBYl6+o>BXD4rHTRH1ahV8NBA-)FSlg|}b{wXYrePXF z?Uo4CZY?O9tH8nk`Q>6^dnH#9%r?A}R(U2y$dw9LAecmGmXI^#l^bDEE787_Oahn6 znSAcYWdjLJ$8y9cVb*90y@=T~&xo@b&mU8Am-eg$2JQ>L z@di#rGB>uVtlC`W>#s?i+#W(ysyR`Lxrc&?1l4`vH&RDRuE11Ah0PwL`vM7qF8OOz zxI?JKa}eAPSDN){cD?+*phylH0l?LNezsp~Gl%Y-rs~4L#4d|#;u6U+yG3_>Y}r8; z?WayJy_h@L(piaOT;;;Jl;7`VKP}`-*0e1BW64JgsiK>)Yf?sWdO{c#DC{TX)N$UP z7l@MDYZ5a&b=i7p#a&Sz#VD)N`=8#Q)2n!)L^GV$oa5h4b3_CJ**MH-&lBNr;Ufzx zCew#UGQWA@1Ri-a^T4;gg-@;Iz?j)>SzM8%MoGeWEQX(UOvK+G)aq zxRR_uU_)VI6{pZFVk#j_J+sWt%dZ%q%yHHXOoYrf0!3+$*541rPg)xw@R7Tg&N}(eBmZk!O)T&FQ zYB9;o>oJbc4<`kU!U}~_d`#!KV;WV^X?)9p3orBwMBSH8h6RUcZzaEz`IOaGUeD6* z%CMzM3gbEjU&812;59)r^UI&QBN2ayZu}Pteg66pAOBM(KN-?gl7lV;9ty>r1*!;4 z15xdDXY2{!5<&>C_4qk4pd#FK&aB3GL77fub3BiYwceaAy|mj_q1v*nXo;Yz7zd%P6A$Mh>*vC(5{tu%nDB8^Y@D}mhfdoG!U~Em8=P-+i$IlKhe+WLp zI~4W#=@`D5dDz1a!ifALVMOfXogW%OK@m-im+6M`>oO<;4KIw4Gn-EDa*!)wD+9q_+E6EJCsL zo$I7eS>sbydJBbpCm&K4aw}I%9{{buuLS0NwP&LCU9qQ&F<3$xmQ|#XT&>kR#p(<8 z^aM^+b+h{!Z&i(&Nr5k%YjnTmJo$P~5IJgJX32U~g(BGK(4H@shKJvNhsVU&hq&&| zgFi}ilOpl#p~W&z{HGAhIP?fz^b4vN~x$f!b{n=v?eu|F;dHCj9+r5&M zc9iH|caDr|V^YeuHP;?c8b604i*fiXG*RzMgPvgo| zb3P7uIK_tEP~~2zb#=8IlV!pa;#t8;>cJ7nw9st7z?CGBY^d8~GSeNA7zu&>MzAfe zU+|TR(h@dyd73mFa6^J#B{-z9>0_=-pToI3146onHeU6r=0P9tKsgepdJoE}`i zX_yB#Ue@^Is#X14w)Afry#lUKb?EM!cW!9+t?&S7aG;+RZXFqHX1{;&==#BE^On}| zMO*qeMnfZ^+IDTUZp+|cG`ubvSl_>;bS>GHtqM z*WJghW9;EAQF>ge!tWj)9k!nhUOqawX*A-V#m1r0(ZRLRnk%CI&6_Fm?O(HDFxt?s zVJ}n3w%nt^%hAmPgPTX2-LJpvvh{4~9D(Pdkx5!iH* z%{4H*`HC$=7p)(S)(>x3JGf=Uk4iPc8N*weU6m7Uv}m&p!kUK$N9OqH<}DC>IJ$Ib z?O==PTAQ~-MxWNU{*l(u$l}&zL!;}5w~n?v4IHW6iig)xe*K94O;<#h3~gGApELR7 zL7pDm5)EFydCTC)2wR3cLmS!h;M$(n(58V6Ti3GUp4OVJqY!qKBY-r6YyDzJhY^=o zWErB_ee2)*_X71bGmF+aZ5-SJxo z0r=_z>sgV8*sMjx%q6--R}61uh7a5{0tq*)?O+t+#MY&Q(b~blSL+4`Mu#pP#2fEF zk2jmy{^R>cMz(Go^d~$rs?GOr*br?R9AK0ETZAdEh(;WjTskyhwB0heSwHU|;wZOx z3JeTy*`m>hHz7uk^kUN2=S{_?W@gdx@cH1S;@7R4Hi&{-2A{bVk{pC+~h|J*|<=g9AhT8;qk79M6RtL=!4^0trSSpxCN^!(4Xew`-9zhK?Az z)eoCNpqAunc%8`|DhiH8L_9OMMu%Ja8H^Q}IA*VA_EmQ+O_sJmmUI{!hB-iZh22Qr zN27kd!}5|JH2A@qK~~|1-!ixfwISWIW;?5pE*jXnrC%leke63ACgL};b!4>FKeWj) z2E^0vM%NE*SsQI;V=c+39}>NjslTH?T4(BWXv0+6wa z0ZNHUo7op1Ikb+o46OJ1POI3Dk9cZ5oUmpPW!k@%EnSKtMJIWAWkW;Zu$&4Jj_0>F zZtB30nbne+2hqxFd1j+VP`#F^oOH2Pf=s#(4Vj!V8<5Fg&a#}fFw64b`u>@jo2#oR z-7Q>mUZZ>Vw)JK17wpm!L09~e$m*!MjH7dZr07VOiulD97G&9k3*<2_km}AQr+vuX zM*uly{%gP^$8nW57OCbS5z6x(3nEM3`mGGOA$?yO>0BktC&=o{){{^JXA)eWX_YDA zRHj7+pCwEo4s|lkyfkZ`u|qq&)XZ$V-4F|}S!RzSNq!`>Xzo!#7}- zlG>5?O_&GOOU0s#W)D|Y7$p?<-bK*R!S%nqs0#Ba9 zdsDb=v~Qq1V?e&v?7ru%O9z&5?`eK^wsB0ksL?bh?>qlw&z<42(LNSCs2|E0&y{7Cod=pT$~Dg_detIQW?cvRkm1!F-+blR`f(` z&>p(B?C#k0^)2sPwc>2MXotwe=0HXB5)7hP95U4KX+ylrq>@B>M>UhqAjrqe7tuC@yi00#|z8FRE zWUv3z6qae$LQ0&YyN}Gwu7*r&rvQ7`5@P}XFGl3YvNrCwI{tJaRyrt!+4WM{?0VUC zn>#LRV@RKO)9?f)k6Rk#NxMG!HySFQJS1nZ;iN4y>WgX6SS2HMYZr6w zT4D?j+iJ~ha91?81hPzFSecHc3r>`Lsrz&pOtXB9h+k_5p%An^Vd6Uc$MuKnWs3}Z zki{twY;*aofCY$Igmwpq9~xdf=lFmZSO0a9EW|BbLu_X97yBcy;uP)@#n;cIEXrIZ z!;UXiiXEir^FNrM_}UaXddiyIg&vCeLS-X&;xm=ayr#&kp*sB=9@Le=J$qTg?wn$v zooGUFZC{wZI4Ll8K}QnL6Rnai;Z?b%tRXq}c6&Vu2cp?kyZCiJh1y8A1=l2uRpj}^ z=ev8t`>rU@md9sH`IJsnwqpCN>I-aED@EW~JupB|Fqm+evuFu;@P{U~a8*jMmtag| z{l#9#3#5pY|DB#G6fvQaLG+iRt(5CmgUUA>sGm%OiYwJ+aXAc2yI8x3*5}4{5YbOA zJy``D%!=yK&@i8>+rmTz6CoY}@M@rIFoM4NGxmYC=ail_P3CLG7rO|NP}2nO_;CmJJ@u(cB)9Ev(=>nJo2f(t>ZH=LJ}Okp+;#PkxdwKL z)P$3qja9vol#=@-TNX`my`ea}+_Wy&FZJ_nT*g^mG)6MML zpPZt|fU{9))W|88^0i*))i6Ruz*Wr%&V(30If^w$V|F(cPS@pSSF=nCz(pW)&20C_ zDePcvI}4EC=dx)*!d0OY_U22dbuKg6ym~Z$jlaKc)x}m3Y&AKO2HOm~AkPhE5qXFM zpRjk#Tv#Ao&CdzF=CZ&1*w#|P^&qGMG*FWht$|#z06|NI9Fll(dq~lA)YXxn``w!Q zBzL=Kay852Q)eK1NFB)JBzgve~)Wo28mHDp~X5cNJf_u}Kb1ggp+f3z)Mw3v%33pU{ah+B! z33)EX=Y^WdyaozdK|f>y*vIJ)2%ebqBM(hcuKiI^l;<3pNslqZQHM6c#g7RS3{2%_ zux`q&^l^i?-5xThy<#OGb<=aV9JX!ro9FJQg8Ldr{p&M_N)1!P<;J3yUO4Wa_nK7} z#F2p5+<9%-$%O^zw)5vyX<9p=DBDQ=^PhzZbY)QZ8alUVz7)0bCy-ZD1Mpd8xznkk zSPhAv%e?5M9YmG#v%2Ajc+m@B{xVWILv2}dZV39@#99y)>eZ=MIK|fdx^^%B!!5x* z?Ru&3+&Zz8)^u*B+QRQ}<5gQY5Pm!r!B{d6>BK3WByceQ;T65T^E=uw=uew2{4u{H z+V`~i3!_rIcdq-U2gxe)6aE>sVJJ4mbZ=kcC^b*{Pl0O~jqK(}whv~3dRxIpc~b;N z$gu*OxRL$hsuYcy*(GNXKmw0PT$KbK?5NK~&QgedIhz~>NU$xYV#&h;9Y`P^e$_cB zT`+U}Gr1#HpQL+0?xMVAMU+MCQhY}Y?+*~BayDuc=BthD;~!|3DM}bafqUY$d$>if zU(?P(cRJLtK=%T-)6l_%k6enhSdO${JW5PkZvs&~gJu5s^0u=I$fKGwCG?P}x=g0} z`p_6ez7G>(-gONDEJwbDby{594&DMvly>g8qh>80*I_WIt=CYHIS>xaz6Q8C5WY$r$ELqX^y#E9CiGSn3Wb0Vz98g;qyZ{|4ito}y! zsCyg)GT?%#6rW(N7r!TPEeMtn#B=NZ%0STycP=@N)ZbC}3|JkBPT0Ks?5Eeq>N_%V zthhKcVPiG&v+NF+Yrky z`q)w(eF($z$mV;(4Bk@7{H`=hHR7~cB7oDF>ThKJ@c4PBR-2hWoM8iST&edP+1pkd50#?+ z?To6B825m3(P+zpBPwJ|=SdaaqiFS>q0XS5DKpBW z9&o8;U}piKHj?RwB1VC+hDs=Ec7w|(T<0}$cVT-wQNFoopCb+$f?%x_36i7Dv3Pjj z=tY(T%bciYcX|fX@P>^;b@f|-+xdIuGNhecYbhBDy7rz;s}=gX~Z)NXyq8c2W=s@Q1eg|SZ@jB6j~aV@uJbz#eMirEp6 zy3B%I3)2ogbEJ1#6{flT=V|tJB*1T!IAX{Y$OCe)RMuH2F>N(f2-D15c!IBhCrn0^ z$&`a?ecu1EQPG&|^Kg%+e2T_0YS#QNM&v2eXl7ByX-kg-xrz zD1Bm$YAK{=yU#(=THEV|Vr@BSs0wZtKY;@<{ZK*x099$hKh}5Kdq!k2>Bk@}Hce{F z)yTP_TqLdqCJG3vEzTl(+3ecA)}04z;BkQ+QbK&YGa~lxnd|!4jdnE@+Ktz(vIs?I zS6gF|F^cuT-EbAGLCDxc1{i}W6R%O~CPy!lx?>T%r<30H6BGVT+}*=DC3tbig=tcE zihr!c;dyu01E4``HQsus2{ZFoxYdaVNcs$T0&2bELK+;<@F~JR5aWVY9%Zny8WG+q zw&rg?I8KNGCDH6Y{O$1rk))IcHQJZOD$EYT8Atx{uC*#d_4gGmx~lvls?sh@qL;?= z%gaaO?81Va4UMKiq}3Tx1k7sjjcaWK&FoF*-zfs0oyTptnlm0o?9U2{~8#4N@R!sJ)uiCZq0;`2gWD zEh3g_f6*x^;Py^1(vC2d)%{S(-imIvm<hs zr6r~{#U@b*(qMF|lE``QC#-LOhmq6LeI13JL>=FV${(PtnS#E$c$f64H&#?pKNeu9{NWB$tazBrl1ysXx!{ zXmw{DC4a8=5=#EXspIK7%ou0^(~%tG6AY+@9UocY+BF}%9`?oVBNlIbur z$ttP@B`u#BrTkx3@Ub@=m#Y?3wE>(6cOLWHhNn47uzRUDI2OC6m3JL#B=+-IO?$0^ zIB;6Z0ZVdiFaFfrMx;kNwsPua`%H0$%WYk+`Jj<9ZNrqKW3&lag`1uQS33~!L^Pie ztI>7e2ir#I0PwX2DVUgbprjo8_(^sXKa1P&zh1o&BKe?>E(YE39(d%k2kc z{a~JTjF8cx2pr^G6?^BF;fG;P7===SCoO@m0$!q?`RPwF%FW>Sla(t`rJ(bZV;rHJ z$jiq1RjNvN@VM)mPqD05G$lpHNFwL}m`vQ5vvzxuie^`%jI0ITa3gIa6;&)Q=Gdip zTu!Fz6JO?ik|0E`2;~wi6gb0}@E@sG>T`*sNj_ijve;ii04H*^GIl0I#r=h{07Ez~ z{KXv~nJ;0y0#O^;`yO@BV1_GNPI2EHuRE=9#PXl6r-XzY8)}!6dd=h9B3hC@yJ=k| zHbdFG$ZeefTuMPj2ksE*!l_`STF4kQtCT_4rYc1^c7j`Fw^{tTSqxA7p6~$rEa=A( z(+~c*%edR&PO!07_MKv&H$`-TQOuGc-SDOOhRp{ zMP(F;0}H^~zS%z`%P*FDqW0IfpOZhDN9lZ9D7qMLO6v=zz;-F;Cqhk*;hr?QzE&p* z$RTihshU7rcXg@-`(m+LJ7;x95qHt)kBvEJUaN6OSoc2Go%me#f>YXT+l#F_Fy&k0 zl{%e)0ZQ1G#9e5~uL67q_)3sTqb(OW;sy-BX1N0z*bY0!Xe#9ZtCjvC{CVa{!9DGx zjohI)z`I{(y_?%Haz#x3;T~ti&|kVBedG5yD|DOefw)Bm$$K2elFsWw`@4RSMLTks zy8s&1JA%6K@udD9u8OJVN!iw6`wl@fQ~Ea-#qr(G(YYP*Go};JhN}f9n2MoLP(A== z(85Q*a9yM!EU}40FuSiKvc(Y&Ah7@XRDwD*0Keabx8}0He>FddlHisOWzIbo#nG+S zDuC5E5iCHffChON@r|tHv#u+HN?E)jN||R(#epY@ zawGfEo48(O{2GRHdAw_3N5^f%WvRsLxR)A~+X95Zl&J&7(qoHi9>_9@ru2};X%2b5NS%KK87-dI9=Ga5vMjpBH!+{}F@sd>*FIi8bWBCRb4k$)zEdpiA zQg}?q;WmBCqOa$k-R@hpU$A7Af+b-PMM?6ci*Da|fPs=o$$34+kV+=DmpdU*r_MhK z1~~+5!Ha?P>RLf4K#Elh+?KKo)x{di7&u1=9W$JtrDm~_{o^TZ-BHzV9J`ATvX|a0 zsH~lYt5;!A@6tQ*^L(I1`{FTk zfohuF(NlTSlizT?F|RI7PY!x^LC00^4?LP?nS`3=zj@;#h=_u8tv;&v+hNmuf!yl! z4CG_yxJk|q*`sEd*lfz#Nu7B&rwgGv-)8>)S)FO`G%MAi|=r(|LfW#a=qFL@qIfP-&*ec=`0%!8`-RneO_%zCOvxU4v7amdD8?OLaP`XQlikk+YS*Hh{ zc~To_RoBbbW4i$F)nZk`sXBVf?H*`!{dRa?m6I5oiZH|YOg@dsGOA_}_(3ys?gK_h z1BC1a7PV-ffCEc+O`5bxR`kAi8H#fksd2-}JYsKoO~Lc=!2vb9}b{-ZEnNzBfVmvjSUu0 z@c=?JUXLe3>C|1yusWA{!!eYe6BmqQe&k$SnUXxnuy|{0J@Se{zZkIC} znWf)Ka!Zq1{S`4E5q4klmM<`^r2DX@zevxJLlYKeX-3vESQJj z6@-9B&e2Y&olpg=ZNHS}hKkI}{{l{*@>Y1WnSJDx^QTm)Ao(&=Q~owsz1LN*8m$nL6rD&=i2!JX{+F7>^Z81R-yilmIKV&CF+yPYs? z;MVzD%&7$+MjFFqTs;9Vi4{};lJda}Mj{%!f{m2=FcC5}MQ{QzYKa-D#yHnSqDOSPmdvdWDs)Tr>FxQ7 z`}=rqw(9=IwXB&d-9K+Q{{U+0>Rd@5bn0mw_q0FuSxN9JuKcX(gHlpk6aIrwJq@nG zthC>+Jf|mG8H$CciRw)CG@kUKEvxo_Ij8UV*)Pv@zvL3hsuh0Z=^T?Tz3}$4_J8l{ zItAE`#W(zZ_5QD2T`%$;zdL*X_j2_~IHsrZm_Oce&i=oxlG~)jk6tGx z@Uj)PQ~JT&Q^EmTnM`^|` zQ8mCuvC!W?f8VL6sumzvSyt65=INbrH5Al0`GQnSK9P5Nk(PMe3bR;xOQyAvz5HFy zwjv9PuFAFoQrz9gtzvv)g7@IH&RQW}?wSQge6H*E8)M@f?PtU-GWabAzfv+RgyS4S zAhJ`r`Dnm@;fGb!C`@f;ZeA&PCSc+q7cdn7<~|jeBx3@6i#+O?13^}qT=#EMSSau)hO$QeWzZhE&cR4`%b+fYRjXR z!*WYj+CvBj^x%tUX!AR?vC&G6zI61Xxktfb*6I`XG z+U2}d*pd+6q5LWSd$8L7mr0a?W`A+UKgA1hhREcj0@3Mb_>oYL8j7rMy;8c;G^pvsXlXDuPN|;mlxq)z z%V)XLl;Y%UWD5dq41}%}2*vIC=o`)L65teOz68{NTXSAD zq=UdB6u6#N!f*)&8(VtoOzAxb@|L#}j=!8SEk}HcqUA6CIV2{Buz6@a10H*&Xbuuq# zIo;^crB!Ly7J&vv9F%^Yg%PYJP-n|77rF4`BD#}wk=Hc~6&VvlhZHe%HqJ}=EOZgj zGJ{nam9O&dXC#q#j!bS3rHR;5PZp=_;e>-t`955jfO85oRy2V2>|F5 zwCO{EobFzRqiqk>S9a&s6WD*V&&ao(I^-Sl1I&A8hl(JmYlG1{c*RCTPmF+Saej<- zDdAADuiytY6{J!EWEt2mH`yV`Cp*1PPQ$~O30g&jci=4Zn|ts(U6sOEuggPCkVZmwco#f^UvweCkBi>Oh8 z{XW8uL}qyezsd%uFU7Jg(UQ z+|BHo#g+p_+Tx-?$E)tziIi^a>hWY{xi3eG5x@84-5y*T!YkaA)nzts5qjs2Sl6u< zebrCuKsrKaS~i6@xbJs=GPw60dy|V`+6=htG;eQ9*_MDNgIGIQsS;p^Dv>9geXyr0 z=v>^AHOA+Y@>vN?p1bv3!8ERtX&kazQdFWWW5Nwcr5R11Xu>!;Z^3R?X8wI`U=B7= zz=j5cXjcO|df21&z~QP>GMmK$NdXY{2a6~m*JP{-yBx@p_xCKM3m`$W>&K+^t^w>B6XNitIGG#Yr|*@zZywTkIJETlU(tk-7?4)c z0Drv;pUYJHxK*rfR1>xRPaUC zcux{(5w_|oAi5pPg9~ELBk>K5X7-2l{;;zWcL9|MJlpkuQ81>55`jN_RQL!3?y9x* z5B?BG)WIDp^IpM?S@cmGy9Q^5`uVCR7;;49Z>|sk9`PfpV9$7h+HUL zDI;_xX$f4m?xQY>LrT6)fF)`=vWCnjq|ogCn^Q#+Djnh>BA>=Jz{HAOoZRi6YOg0g zehnUdoP5>i6}gGR!hAtPgCTuTJ<^w6yRW`gmv0>6AX0HlGl`AOb+0&Wp5M4Se~=GX zSthA;k;bGcBmoYsjGJ!!oM_=u*PRF%3KcStR;`s>aYI4X%BI;Zen6-bmdZ&*7&ue( zOBd&#y!j1rgo@b4n2fTVC!^(37ouW0&ZA;Z9I3q_RPMd9G@%as#-6=T{lZ=cpvks& zPaP3wTf6_8U|8y4BY%kDIXU&mrQDI7HM(z}XdA9{Zj|p4ubWoa@Q4dFU|Z(#ZWVK+<2ty5XQLhm4jqn(N}@B#B|!ey-U)#0@>o&w8|YG~hs^d#FcCk<|~fGq3aB-B@(T z882D1=$dye%B=tOo<`97&?jOLWFq z8%KS-LIWPw6Ne*y_PVp9XAcRV`{)i!ESH``@HbnU(f4syo(sOe=cOVLuBuOuqGZf^ zS*DH{j#ECG*R|=@k#eui00S0wM;!ZQYPE=w#ta{&@~Ibv#8|aDH@kxqH_i_`y=GS$ zg9S4OfFcb=jfJh%QpoQoIx~8?tVrdA`AMrQ8uk8aw?lV#hm}@U#qkc&3)uCv*1Ryu` z35XSxjt$-5ZzxrlK?F6_FuIv4mrp3Tr9Dft9Z*EYa#E5hkbK;sf#mCc{{JXGwXk!< zzM%8xGEaCyI~2BXTz5TwL50QY(}RX-r4@Y(EX`rKYx&a(Q!0|GoPW#kLe(`Ui>>+U z)6owy;uti(TVR0N-gYE}OE(F~!gZw46A8}l#%O2PalbHb%A zB$cFpZ?3-3SW1%wgwV{q`c-{gH6SB`+>so6bu%u02(L;_M*w_^QMEtXmCI3dh2=QZ zuf1uhc*oQ&1-1Ud7Obmzsu;Rzepxf~i>6mxom#W|)6@MSJEUzAMiuFFOGJb6x(YZ{ zt<0TAM+;OaxT8|mjTk>m$bmPzA9Ic(#1&WQQcfx=a7OOKFR{u;5=%)5u?}>);BLzx z%9S2-?lH~Q;agq`d-Buxq7Bg*q*m2;_aKSZ=}TWcvJ1LG{jqM`t8KaSwMTVQu_j|H zkX;cztO2p;_kCPXdvmG}t)WI`Gr+U~EJ67MUL5$Q9?NBzX693)E~2Hd$Cv5jL!%&_ zp{b(KkpX7067vY=G#Ycb?gLIU-u`Mu?%I3<=o*X{I6}pCByHFtqq8TMYX8vCL=`T*w8oMNr8!}SOj}pA>YHA;9qG81+T)XE(8D$wnSjeez1gT~x%g&F(xs)`; z1M+25NjNWrxJ?p55Xh9)Rv59Fx%Nti@5qJs&SgKpVw5?9hJxDr7Pou$ZEKhKZ*OZ< znJz~yodl(mK7hl?5xny4$lSF#>y5)?EQgA+vs1hG)nQZgIH0pcxOXZBQl-N*SxsLBjAHpY%rVpi7A{FavImyD_za{rno7Fu;ZK4^u!#`G(Dq7{r4 z&x4V}w`Hwh4lDbp2Y-A3L#>k_$g!(Bm;J=J3K}(|k1pWp#g!WL7t)PBu0EtHGGOjj zQ0dwhBt>KfzS8fma4QPpS8fW9$C13>-yNrx&5dx0Wu!145jce4@-37O0JU=O!$XIF z44ERXkYcWHy`SWWpTm6{jbh}?13!{NPFaT#E5tkTX#j+`Ad~W&n-q$g1ebxACVb$| zSp^^2>wa^U#Kr^PaMgrZ-jyd*Pz|$2QE%StrHxuK=L<8&CJJ)0I2fsDt2Lxnw$X1 zB1{@j&g|j``V;lR&2TD zDsn7yJmRws@oU^V69HPs=Jb&a8`8R>(eev$sg3G7g6_~z^NA^Y^_9Kw!y${mbtC;Rl(>FtDtvfXC)=G7K= zb=Qy56l!!2^DXZ9UQhS??+nHOMK8l-ig(}1sBJ=xVNBZsorbQ{#Tn%dbY8}^@mRDB zvM=_HmrF}<)?HgWb0bM(nRqDFA_j8ggua09G*Psv6l3V0bJ?Sg8tA2!%i_Pp3_OyM zrZr%7ZgzJ`VjL#bEhW{V@u3$_f%Nswg zsBXUQ^;tWwddYqt_RiLSlBPENvlUO15AIvo37dEbzTozpgGAM)NDO?=)}42I$OU?q6|7}UlxjJlT}H|G=phMvPbY$DB5J& z&z-CdcqkXBKMnvQBv!mPedbo$y4L-J*6$UUL?QVH;vtf z!tH7i7^-MfNr3_8Ed*o4+tys%LoEU#STYw4S#PJKFlZ7dOW9O6QG(zyUwUsqa3P{R z;Xd7^m*Tdz!Pt&>HlQQ8x&4c4eaPNkARX(bxXL2n7z!6Da%#t)yn{Oy1=Jql4TEgL zl#x}%+VVXJ@@Ac$xlluG)#9!4`4=!ma^Wn5!uDs%)PBExezISIQ+*Z9DuWNQ-_X-7 z49=Es-Im_6->)_}`m(FifiK(qM{Z3ql)sx{I~Q}v-;%=?E^h`+|3llpJfzx z?J@RaDwF)|qaJfelD|Qdn2pl9(h2~Hl>#{Yv>%~*b9Oz>wV%dy3yU-c(#dH(Vj(R? z6pQ&Z^43e8Jd6eXk+~<4&3&6)wZVTU1JzNN$Ai8tMe|W z|AG5(0B*kZOa?eQpb5Z4tr7DEZ)mlwa=G6Mo);0YW~TD~j^i=7?jLoJxc&&%4>7PJ zU|kC+7sW&70Vzv95uLr9qJKYr|H!})s&J^0J?;0_9*+E*-G-XWE;(T-cbUS!L!E5} z_?&Oio3U@@*}8OkRc5KmIg%`{Lu;q~e!%!J?89;x&Flx;`wG=ukrMEbz^oGLm?52s zxpc(=ziqei5|~D+*(z(mY1Gc3S=`d(&zaEkUt5h}jr9GnKB1kx@k6L!qHsh*P@?vg zme52WbSj2;+J(`Q{w2|Ar$uAY1^oS4OWI5Ho|~3#`o1)^cUj|ziTh1Ft?yqV1>Wv7 zGp{;~@jQ zUZY9AvXdy_R|>(kF)WL)I-4M^UmBa9iP|wIz*wd%r~&jG>F|#4h~Wu1>Mq!XHFktq zrGzyw<914ep?i^^_`C?f>W=%cwhG5VO9j})bdrTc`Vyt=wYXt!#XoRP&$!N2ux(So zO6XuQ68iRMZd5IyU#XO%0p4cUzmygG3`4tky}ODk24WSkH{PE!?68cyC@L2$G^=GM zW+Y7K=WtzVT)j{NZAmN~%Ae*r0owk5j83lHug_nw;Ddo5)~a<-v+HX;o_Mz3Bw>r) z6m*j`=tG`KX4GpLGPj-TBAv<*_;t}n9W4$LQ=urk|7qORc;-P4v`WyDB&pYJKA0>; zb^u)j*kK_Au@#6*nQU2WCUE8KN*SqZvuW+JZx=tn-F1&s-Al83(?@ABZ6SUNx>b!(3on|B zOI5G|U^tk;{AxowqjC5JWfJ|_C-!@h0mGehO-%ri|HBW!H7MozEYa4xv=T&!d=dnz zqld#P?CIni?({&PR@tYY$tBrj<#>&+H5l7>#7@InVA|L~T@*+WG)A-QTd&aye5%P< zUP76UE$SKBqwvsVktRGvpQ*1DTr1Mdkxxx?$&|Io_G{()KPXp&Lb;E6?DGN>0fM=QMbca|k)3BDfcd`n;_DTH|#BglXA4eWD*S|BtacF?Q zh~qRU;Q&O5Su8Ycs83dx5@$*j4CcV9YaN^g&Dm8h?cyp+$SNT1Al=<&GY$>Rj=D;a zL<=QsCak5si%|)`NV)RmQvo=gr5_$IiR0EPTv2d}a3e;zLri=Q= zWptCGP?4q3P!5$5+O?oHwzn)z-;o9Nqx)JUAFD%!9CM~rzFpduGY1g`^xnE_6xzjC ze;wk2c%GVZPiT7i=o2sGa@^;ZIe5S4X6D{c#TV|iZ3mTOilHP6M-kn<_d~HNmNfLm zCaTKcWBQqq^r;BMJczvv@srL^6=?$H&)ye$8*>j_L#|8>xiZ)>i(2%Z!N1w38$cG= zU<$_*X11P`(!BZF7-V^;Whk1NQ<~6%BUZorDk@6fn6bdSvW}*J z6ZYR>a8ccpL21V1d)F^J$p^s>-;ItB6jU@&3P$ zb2;@f8kFH?E+yeYN_=3Cx6>E_;}3wW(n>h!tE7+&wG<}>0xtJiT4$_&HntT}F!k-3 z$CX~Q3`Umdr3QnlxuWoeViwl$kG}piKOh6xvDlfgSkdEuIAG;Sc93Y*-c_IC{^G$Dj0fq(Y zq`?uYUDamSfBy_a=x!~C<4HLIl4)045elSW+u*FGGIvWl{o0_#(E@Xssq1A~Evz67 zZ=Ww$a@;jpa9=*>Yi|)vL|c4CY~^aCu!aY3SF%aLAvm8rkCChae<;+l0>qF)R4`VI zX%W-8%p+cp1d*o$%3DZ@v561%?BDt0vY$ylsQ1V%Pf>lz z=}QoO*5N#jAoO9IvX;$E^YdxHL*NudP>CKo^Gip+_O$q$h}~n;+xu30lM{&A={_8t zhZ^fGowu+!NARj2ncx6cmYkydKfpJt21Ab4gm2ebCT}#2;#GbQz&gnU~hjAO-k0Inl_ccv#CG{P9>^O?ZU>x>D1;*s=!sosob12TyqD8Nd zi#JyObsgtKwYIq$&Fp!0ttQ;6N*E-2<@?LqN%@!SRgt@K_-%KP(e)pwb9Kf547wND z32C!b!K(i>`Xf;*{!1L1&{M3L{o1cxLU@NF%`QqAYUH|4Ygf%+I;GVyRG_#%ZEs!b zjlwpSUk({W&s**SgcwZrwUYOJ?qki?anuxEJdu8+G4L-2^D%&kMbbyX)DXIi>PDCuM@J(b=|c>w;Av)t&*^! zuLU_@$}&>E-zGY2oE*RPur^HXL#9OSzx8^fSuk;tKXA3MacH8EedQ?8}M;5;#?gBOIIwNHGuE%m5#C~i2-RW-c*2~ ztW$Mx3?c^bZ7`Oh7M4BAF_=lGou>DP0)|8rP_~>xtSS5`hT^xptC}PJUx69j`h@qL zyvsV6r{=w#ls~yPu+@5OOcBG`Gne)p>A1-a7i)TyHb6Ajs8wA)fclT|x~osh`|o~% zVTH%vvvzI#3$eDRPz;>`L0tD^X|AC>h(264;O9CytP2VEM?X~!hA*FeKp#OP>D(TX zEH<-8zB*I{jH?QO?TV<|?TgDh0Dn}(=pmwS&^!5|*_kPC##aM< zc^L|AzL(FMDji@g0%*IXLQ7RCPPgpq)P`bXI^)x{L^NU&zk4s|W~V%zvsRh_X9K73 zc-RJWpd&?Xmv;(xJ5agqU z+$?1yAD%=-_xxqL0qP7C@IqIytm=bgXG}(;@7?L`2@1Co7=jEi~-#>W2;Gk_2g{%1P~QCIS#o%gqpj8 z+Omv?@3etq!LWQ&U(2quCVou$?zIal#n;^I2&ebj>P$vb1)iX^ zRNQQ(CzVNVL|n_*emaI1ig#X-H$^g+!-ia%nW6j8W#|sc7G+yByj3Cs7$xsgauC{b zIc>=g{MT>f^K)Oy_&(XG*r}>}z?#EAaHIR(|4axyFT#W0E6wgp$^i~qiY)oc15);x zUvr06O-(K#h`^FOzl4u0q(Yf&%uf?jubJ8Ui4N226f^-Y(jkG!l*WVK0hukBBAEte*-cUu0A7q8>ek$n@vv#fuL&#sk!}01<>mC+JZ01c~8rgyAc4{dSMM+4C6AF$K z+!uC|J69d$bDL?2?7n?~hj7*XXheTgIGW!%=UWywvVZttTQloC5jeBQx*vuiQd2@y zqYueiwq)*zW3TX0Qc1~*-qw&qSzdJ@z6{jN-gQTqDmM34t1L`%Y*2LOtvPfhHo=^I&@&?t-U|0-%$7(&fag=!NXbXgz(YHcq2+_xt^8RO&=0OW|L-@Pf7zN9+V9ir-F zkuGb-?7D^0PtBd9v6MeEcPb(?8`aUm5A?DmHPWLKD>&sB+VfZB1?pkr1QC;GDm;@g zj*XG>ryhG~{?t2G{@+T|$qmBZPMJpgxVjiRH#&AVnD$G8P??gquUg*Rh$WdEM%^pyMYfHuSQr z)YRbG`HMT(na$s?k5*Y@Bcv{L@cwyuT(a#KV9enh?q>E2mkNT49Qq`q zFR}oL>vFc0PEqdt?0@3JdtZ1M_aD{jhHq&oC?<`f8Vz8I&%M#xLB$#FbGgve-yov6 zY|y~pwj{ob<-yp=F?C-WLqRS!pKFFXS$>Q+L{OaXn- ztl4oAgQ57S6A4QYANQ_N_T`*2e=5w{%zXC*!(9lA;Tdf{MQ(>VXTTDU$*Y`^#h*;2 z8v-?`qoaYkJNaxBn9q-&C<5&8tt!Z{j}d8#WE^%PM-t~kR(s6>Kw8(2U*`RK=T#Z3 z(9y(rEZ`4LC42OH=UvIiEH2jP+YZIX!3Ox=c|7wW#?Z*#@gax%1e&;Zt@d}yH*${H zwNsC-%4vmNgHp2s9=}8L@Cdj!vnQ<&1t&TqxK+&;NJj%-Oq@Xt8TC=?6_oH# zQ>a)9A8`xZ+}|45Xh`2(JvM9-2dglAt_s%fWzn0u+4Y4DPGM4O0F&(3v?L8Z($eK% zB!}93o+&i1Ca@rJW-7!&ffdNpl8=UuJ0aoVTgU@T>H?>@Ddvu3O?+Sdo&AID58LHtwi7dx5vKFVz)7}l!v|&xjL0j^ z%zu0*9kFscxY51((xK2;Khjr*aH${82dqRBQ&|*Mai<;jNULHS45g{hdD)^o|2d>0 zG=Ku(A3)O-(xhiAK8F^uJmm#<08Nh)GE1JIU8dI?)K>ayZxHHTrBNP~6R2<0aS}<^ z)?rZ;i6f6+Vu<2$z>79-n{o~GP1l)-`KTO{PziTb7n>fP&RtW0doj}~Xq)0MS7qiW zaUFh|*;5yrL?X9qzX$~>54W-mJ|$qi!nDT}!qD>)KsG~^1!;TMBRLyALbH_&?DpNdLj{E#LpC=bcZe)M{`!;T5DvV>d zqEpJwPgll?tbH+FZuYa6`cwsK%QcK`WN!So1^MVzz8nZsNLX~&q0!cT3Lc$fA!Ob6 zpVjf`}&<@MEV3UE<^2R{z=k zhSi}t6j8x@zpq{WB?0xsz-t5?V$qt}!``F!(9qK0!8vti!c-4p`?!}F#Brf|^uN$V z=-;&;%RZ#_(7NT@J*ejyG)~3by)Ph%1_zYY3j(Z#oWDKTi}@ zv{buve)L#KzrH|X_!rMaE6@3!hJkwObERVD(l5O$=Hk8J7jo1Zn+qJwQ zRg3gDGk-_8Hi9D*uX0uQWN5=T9@yNMUOW`OHK6Ydu=bbrfxG4Sa3H*!9KZWEmc>P* zs+6klW~W)nXh1mp;FZr!P$lr$^d^H2y}=O#g>RQg91medu0zX$xkW;bF%!y6o z`2lP$+JB?@##Mt13O_vTbTST8`mP(j zX6O}2eFNB9tm-@YNC4FwBU}^m=mBed)UtlNyeB+2;XZ)kHx5SDU3{%O2JE_JmhMop zbN|KgI7Y!{cV8sK!^4Cd#V?aC}#u>EU_iX9o*J}Oa`R(;dp#NmN;3NAV zZ$LNk&0rez4vnK*q~ZX2IU48*z8Z|)h9b27V@XA?-Q!%$CDF4iV&E9aJ`?Y^DW4$w z{?8797UGI9qmep*p%mm+2w?Lc$G7qAD@80l^>|QjUks?(0@JZ4b;G1yk(0xlmygcb zI4nnu0mZTK%QBimIs-w!3_*OPIN}3 z$Gi0!8Yha`HMBo$tFiPu;KyQlSdP>2OVltvFPrX+@%Tg0Gm92|>OX>}NmYiQWqm6y zDOrH56s@UGLIf7JLCp>vuymN+9n>w0KJ)i`+AGgm5VPC;gR|7Yf??F6LaO2RjRzkp z`M%k5HOrytcDPb$K@TYxkzKgMswfR>q}L*n#oX=hM~akQ8_{*`B#BA-e8m)3Ka=Lt5Jw4 zgq9;)i*ym_8Y;A$Wp?2(E6iZRY0PPzi#yHCX;*l~o|;!b6)B>nK`-kkeP{I?h#c?g zz0BH)opuG1fzbG1fv;{j(5ToNGXj3|zRE%p#NmXGehNwQ!BckKI)~)TBr*4i)|UQ_ zfOopf7}YwHliiR1otd&`_VaHGtn+8``JaCqM01yUq@gIeiM4~ziDQ+>{5p+EkhV@P z=*TPHHXKMOq0gT8V#~Jq^j-GKo7fwC5fC!yX;v;kdAoVgi2~xTn)un-P*-9jLGg|} znP-3)0S7sOw>@JhOsR~t|0>yBcJCQ@-_7i_^$bMyBq;*_v3Fg)kb~~(vywW@01RVK z+0?(LXOt=m%&TUXD7>0$Pno;l?Da0}|NGlUmB8U9R+@T^?8djZll{?i^j&8O0{CHl zj!HA6`ZuxAbo(mH;(TFgG_|@EIw7)`>a*fG)UlHoRG0l@H${6pm~=<;3K?-# z#DXaMeFl#{K2n=-i;t8F?s4J`OGS+9lR$o}3Rynv8dC`hf%rgYY9{-=)IEBa+@AlC6@2=zM;Y4SGM8f3 zG{|u^y1pb#v~pU`jDt6(K?8)2t9+sC9TZUg`c=Mw3J>hqXGovVdnM7xKJcGym-u56 zNzC@}*;j_ALx^d0ROY?!vCs*!NSL332+Qt?5E zIL7|BIAuj^c-{jND|VvoJ{Nz=f4nuCUp~^v-ha67QRPE|R0gYu93R9HfLCBhp*Nhc zSf%(GiO1M|AE>QK>5A)4Efq@=C-`L=U;B1@v6Q)f82iD4kNit2%C%rP5#KqDF2w^6 zSdBO;UZgQlsWv6{oI;*>=*e|_LoiwuRk=dmIxBH@Gkd~Ll#@Cn*&~ zN)-B#zalqnpG!6o(3nIF6t7Do%_kfh()|4LfHYSgVw3i`jQ5F$HpACm8D>af+0}++ zp{qI*j#v|e4SZ`x?6f#~E=` zRN+_iC%7((o9B!(bt6i-Ia>M#JqOq8xp0fY%Yp-svNE87!}%UMh3|fnq|+j|`(E@F zGZ(U3Rs!TQVjSam-F3FLSb(62zCEC945p3$HUG(dn!rH~?|;A`u46N=D^*27LENQY z*l8DRhfGi5r+_S52)Vu=Pp2A(7*R0F6dwqF`zyL6`c#2Ie8ykfaG5>$l?|d{AAfg0 z>LQff;I!W}VmtJG>83F4zM2~GGEXw)amui8z1*YU9Q|>cneSb1-=X9wbSD0}_ti`y zyjm8F@E8f{ksb^#R-^m%PvJh*_lmwB9^1_WOMQ=0R`;uqTGUeQ=7`HtaQ3XCLguR@RH-v{aj+IGO7fDhzeyp>VOfs(A#?&efI}E}#LM2Tp#g z(hHfz$I#oZ;yyCa$o}&^Lp3serqroZp%lysyCAY$Q&SZ9GfeH24cO{}zbBjE(>*I@p2m0t|IXK|(z~$aU22F^Z z@{gs_c1F}n5x>$C>54*=BF~}{<`^t(^FU{DXHM9!D|U*S*`;SJwXRli-f65*8LLk# zI)Q6}c3uB^aYOPA_atVbOM$Ki)n6>MP^zybrY;eFW#7E*XAO%(SD*QhNdQr|0se7K zzrJO{*GVq_8#@8`O%w)xx;Ov=5AjS?&3}+-2uA@*0ICc9TD&;!f{G=9G^hY2$|2o5 zUgYzNzCgUn(cb+sSpb1kH&1}f@nt~I|JtjOR1r@RBta)F7qsx3gr}u+2rgst-zaMf z?3mJ;*^94C4D&}zId=``!yc1kV;;2;jPd-&TWkWg#TKGTu7|gTJk*@cNwWo8_%x{* z_0(sF4R!Q5EG3AfHJ9Xe$tK5As}Gv`8=^Sd3qi3y-+TFz&|gpdWqOUFRkvqD#_9^; zo%}2a$BT|@{-vN!i20d1oJii|z@QlC1sx&4o&f`Pk0d5h)qmV`yc;e1~ zT3N!RupQrn;V~)_2$m-IV4ie{2J|<87iLJA=(Ej4hsNY$7}J$; zn@bKTPHq(0@3p>Plpp8-p{D*u_ajaXWd+Ud zN4(JYR1b%(QsCtTl3857NC;G4M|b6wUU-~PgwD|}To!YPE5_rjoDGMStOdJv+RWbc z(hx-O4N?#yl%FN@c*1$^t~DwdxmOJVOQ`6~$sctQ0E;V1t6Mp~|F%$w4Phyyvk`T; zEQ#evMjBo3xz##eR_LUyn~j8oxuJ6ZhbVn-^1FnQU1vS`O!q};nI{w|m&`7;pqa*? zjF#gSij0ZZ%qR}kXQwj~x^DQf|MJ%chcIAv*nHpX<(uNG154OG0*{pvV0QQGrL#Wv zU*qMvGGi(pV`%*PXj?Tmk*A^wW#$4o%Wu9Pq9k{45^V$3pvAyh3OImTeBvPr*sFtptvbXeb}`C+@}bS}oj-&bya+2BagK@b8l236 zG88jX`}8&5dVQO3qArxwb0n#$XF~_$vrf6k1%991_nc&G4m#MAtix;X69Sl)`s(8ku+O zXj_`c->*})hnA4+Xk?5Y$Fe-D&Rt4T(Q5kj_nmY0^1gG=0>&(U-9xt0XRmzDT()&B z1xg?laMb^4?`mV4Dx>i2#`qWxMq*+NXh2LLW@~!yZRrLkrgXLKKDya<5+MWz+hkDa z(m}Ere<|t@74veFQh}%hLt-#XlmHSiK@$EDA$}kjlLm>=C^MjGV#Fx=ob%q>-FAZ% zC_|!4mSwlM?K$V3^StLh=e*}6`rtO4y%t597uBNOnPz9^qHhZ{F|}YI6U~pEL4TrT z1|5+zcq2t9sjewwQk?044@(qhh~i8ExlpV&ORteFL6nFpok*9)t#!h{Sshes3!7-p zsywxu;tDA+p4jkbuBZSIv zRTu!6@PTB18*pG>FH^X%pnQuYO@hvo=U$1%DBt+WpGj^&8vdi-{7xh4Wb;7_(;oCj zz>bbzh&pi{N>UZs*oqt`FsU8K$~Y!as#1WyY%Cn?X!S*iz(|r@*8!rb&S+d1<8ipq zZg&4zni{J{z2?mm>;b{^bw4E!DgVBqZdcU{y+Nn(w4^zNo}~o52-ha+GEpbp9B~>k z`D#lSPE@3591qH&*41U&z)*+uph=(kx?Q7*UZ?>ejNIsbz0FCCZb4gJgC-8EBwD=1 zs*Ur2R*$>h(~zfi(aK$wyZ1JCVM!w$M(rvr?yVg`Xl@j3N`T{_6z(UhBPe5&xc-F@l9VRZ!WtB?yz=?ZYHCDk)gVtEz zpzC>dykMt(RslQd%0MUB0oZ2Rskm;)LU1G}kjaxyWr3DXFm4sj~FHHD9b zh!&%9k*^5$CM}p(D&C6;~%p3c<$s8ZJ(uCqq9Njix zuNQ+If#{Qq4U{*ZK3agv1+<%*_ z#K)Oot3Dc`4Ww&y`x#3b_>QG^BhP!@p&lhqkJD^i^pxy);g z7oCe9?2|K@$mWrfi^Y(*G6|eb4zn* zzF%cIH2O`R{--4M3RO4x!o~}Z@s|ENW9j;?6zaw=#^LU9XGZ`y7jA4M7Oke;982S1 z+5oyEEK9>L=^04C$HoKR*GoQ!Q|7FBjaIP=;&QyN2f~B&+Dz$TJJQ6`>w%A91h?Q& z4{Zurbg&hpRLNnvH6`~qeoB+vWtSzkx_BARH%NeO)+oEf;>W#-CPZ^!6&% zAa5!fb_{OrQ(Yrr=eG2emmcJsoZE~E`YUD(J4Qk(lElZ6Bt|_@79D-M%(I_DIX4?~ zy?)B%Jbx(*7U#Q+OkTT@Nd6WSS2@q}9ZWIq{QobW+&wJ^F>QZKRyAuppb+suv@J$9 z>x(oQ{`N>yI38|~#DwzQCFb;hEw~-67t@Z+&T3eu$o72woE}G$gF)VihUC#c$R1FL z7qN2(79-Tj!$oi)iWA4rAl98SA~;`W!t;Qr@P1pyXCtQ9)Mh;x#?CMY@I#|2EWC)X zUGSmmI^9#q9R0r%~k|9QQ?{(VwwtLn|2bEHy$bn3D!WmPvV118lP>CC9A5aG17 zLCY<3dXf=9dX9Px3FYds2_*GapUthlPfR=Wb5`}(M59Y{qI^8|Atag6Og>K-w?{@D zE&cbPa76XoJy~@TF%1Zz0o>3AS+!pTA*2*$-~_w&QBCGDItyG5m(v@#*#{}AU!O(1 znC^p{;JRIQ<49Mr??CB5*hEhTQp(I7sst2{Gp8niZM>6xCCGO=d{W&9OmC4GZx#cI$Mcz^FKek@E4=*Crx@J(-a`6ihys5Pyd4ZvKp={28-?!v&x51mA1B%J(jr_ekANdvJJQNOk2F^$)w6 w3$7+`b=*MmxJ|5c`h`o6586KfY`Ah-%de}4@>kLCI;Fa + + + +User's Guide to gperf + + +

User's Guide to gperf

+

+


+

Table of Contents

+ +


+ + +

Introduction

+ +

+This manual documents the GNU gperf perfect hash function generator +utility, focusing on its features and how to use them, and how to report +bugs. + +

+ + + +

GNU GENERAL PUBLIC LICENSE

+

+Version 1, February 1989 + +

+ +
+Copyright (C) 1989 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+ + + +

Preamble

+ +

+ The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our 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. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + +

+

+ When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, 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 a 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 tell them 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. + +

+

+ The precise terms and conditions for copying, distribution and +modification follow. + +

+

+TERMS AND CONDITIONS + +

+ +
    +
  1. + +This License Agreement 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 work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + +
  2. + +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 +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + +
  3. + +You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + +
      +
    • + +cause the modified files to carry prominent notices stating that +you changed the files and the date of any change; and + +
    • + +cause the whole of any work that you distribute or publish, that +in whole or in part contains the Program or any part thereof, either +with or without modifications, to be licensed at no charge to all +third parties under the terms of this General Public License (except +that you may choose to grant warranty protection to some or all +third parties, at your option). + +
    • + +If the modified program normally reads commands interactively when +run, you must cause it, when started running for such interactive use +in the simplest and most usual 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 General +Public License. + +
    • + +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. +
    + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + +
  4. + +You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + +
      +
    • + +accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of +Paragraphs 1 and 2 above; or, + +
    • + +accompany it with a written offer, valid for at least three +years, to give any third party free (except for a nominal charge +for the cost of distribution) a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of +Paragraphs 1 and 2 above; or, + +
    • + +accompany it with the information you received as to where the +corresponding source code may be obtained. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form alone.) +
    + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + +
  5. + +You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + +
  6. + +By copying, distributing or modifying 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. + +
  7. + +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. + +
  8. + +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 the 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 +the license, you may choose any version ever published by the Free Software +Foundation. + +
  9. + +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 + +
  10. + +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. + +
  11. + +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 humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +

+

+ To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + +

+ +
+one line to give the program's name and a brief idea of what it does.
+Copyright (C) 19yy  name of author
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, 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) 19yy name of author
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+
+ +

+The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +

+

+You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + +

+ +
+Yoyodyne, Inc., hereby disclaims all copyright interest in the
+program `Gnomovision' (a program to direct compilers to make passes
+at assemblers) written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+ +

+That's all there is to it! + +

+ + +

Contributors to GNU gperf Utility

+ + +
    +
  • + +The GNU gperf perfect hash function generator utility was +originally written in GNU C++ by Douglas C. Schmidt. It is now also +available in a highly-portable "old-style" C version. 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 <bug-gnu-utils@gnu.org> and <schmidt@ics.uci.edu>. + +
  • + +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 gperf. +
+ + + +

1 Introduction

+ +

+gperf is a perfect hash function generator written in C++. It +transforms an n element user-specified keyword set W into +a perfect hash function F. F uniquely maps keywords in +W onto the range 0..k, where k >= n. If +k = n then F is a minimal perfect hash function. +gperf generates a 0..k element static lookup table and a +pair of C functions. These functions determine whether a given +character string s occurs in W, using at most one probe +into the lookup table. + +

+

+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 Pascal, GNU +Modula 3, and GNU indent. Complete C++ source code for gperf is +available via anonymous ftp from ics.uci.edu and +ftp.santafe.edu. gperf was also distributed along with +the GNU libg++ library for several years. A highly portable, +functionally equivalent K&R C version of gperf is archived in +comp.sources.unix, volume 20. Finally, a paper describing +gperf's design and implementation in greater detail is available +in the Second USENIX C++ Conference proceedings. + +

+ + +

2 Static search structures and GNU gperf

+ +

+A static search structure is an Abstract Data Type with certain +fundamental operations, e.g., initialize, insert, +and retrieve. Conceptually, all insertions occur before any +retrievals. In practice, gperf generates a 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 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 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 n element +sorted array is space efficient, though the average-case time +complexity for retrieval operations using binary search is +proportional to log 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. + +

+ +

+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: + +

+ +
    +
  • + +It allows keyword recognition in a static search set using at most +one probe into the hash table. This represents the "perfect" +property. +
  • + +The actual memory allocated to store the keywords is precisely large +enough for the keyword set, and no larger. This is the +"minimal" property. +
+ +

+For most applications it is far easier to generate perfect hash +functions than 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. gperf's default +behavior generates near-minimal perfect hash functions for +keyword sets. However, 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 once, if it +subsequently receives heavy use multiple times. 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 gperf is currently +used in several production and research compilers, including GNU C, GNU +C++, GNU Pascal, and GNU Modula 3. The latter two compilers are not yet +part of the official GNU distribution. Each compiler utilizes +gperf to automatically generate static search structures that +efficiently identify their respective reserved keywords. + +

+ + +

3 High-Level Description of GNU gperf

+ +

+The perfect hash function generator gperf reads a set of +"keywords" from a keyfile (or from the standard input by +default). It attempts to derive a perfect hashing function that +recognizes a member of the static keyword set with at most a +single probe into the lookup table. If 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 gperf. + +

+

+By default, 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 gperf to utilize a C switch +statement scheme that minimizes data space storage size. Furthermore, +using a C switch may actually speed up the keyword retrieval time +somewhat. Actual results depend on your C compiler, of course. + +

+

+In general, gperf assigns values to the characters 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 gperf to find and generate a perfect hash function. +Experimentation is the key to getting the most from gperf. + +

+ + +

3.1 Input Format to gperf

+ +

+You can control the input keyfile format by varying certain command-line +arguments, in particular the `-t' option. The input's appearance +is similar to GNU utilities flex and bison (or UNIX +utilities lex and yacc). Here's an outline of the general +format: + +

+ +
+declarations
+%%
+keywords
+%%
+functions
+
+ +

+Unlike flex or bison, all sections of gperf's input +are optional. The following sections describe the input format for each +section. + +

+ + + +

3.1.1 struct Declarations and C Code Inclusion

+ +

+The keyword input file optionally contains a section for including +arbitrary C declarations and definitions, as well as provisions for +providing a user-supplied struct. If the `-t' option +is enabled, you must provide a C struct as the last +component in the declaration section from the keyfile file. The first +field in this struct must be a char * identifier called `name', +although it is possible to modify this field's name with the `-K' +option described below. + +

+

+Here is simple example, using months of the year and their attributes as +input: + +

+ +
+struct months { 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
+
+ +

+Separating the struct declaration from the list of key words and +other fields are a pair of consecutive percent signs, %%, +appearing left justified in the first column, as in the UNIX utility +lex. + +

+

+Using a syntax similar to GNU utilities flex and 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 %{, %} pairs. Here is +an input fragment based on the previous example that illustrates this +feature: + +

+ +
+%{
+#include <assert.h>
+/* This section of code is inserted directly into the output. */
+int return_month_days (struct months *months, int is_leap_year);
+%}
+struct months { char *name; int number; int days; int leap_days; };
+%%
+january,   1, 31, 31
+february,  2, 28, 29
+march,     3, 31, 31
+...
+
+ +

+It is possible to omit the declaration section entirely. In this case +the keyfile begins directly with the first keyword line, e.g.: + +

+ +
+january,   1, 31, 31
+february,  2, 28, 29
+march,     3, 31, 31
+april,     4, 30, 30
+...
+
+ + + +

3.1.2 Format for Keyword Entries

+ +

+The second keyfile format section contains lines of keywords and any +associated attributes you might supply. A line beginning with `#' +in the first column is considered a comment. Everything following the +`#' is ignored, up to and including the following newline. + +

+

+The first field of each non-comment line is always the key itself. It +should be given as a simple name, i.e., without surrounding +string quotation marks, and be left-justified flush against the first +column. 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: + +

+ +
+# 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
+
+ +

+Note that unlike flex or bison the first %% 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 struct provided by you in the +declaration section. If the `-t' option is not enabled +these fields are simply ignored. All previous examples except the last +one contain keyword attributes. + +

+ + +

3.1.3 Including Additional C Functions

+ +

+The optional third section also corresponds closely with conventions +found in flex and bison. All text in this section, +starting at the final %% 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. + +

+ + +

3.2 Output Format for Generated C Code with gperf

+ +

+Several options control how the generated C code appears on the standard +output. Two C function are generated. They are called hash and +in_word_set, although you may modify the name for +in_word_set with a command-line option. Both functions require +two arguments, a string, char * str, and a length +parameter, int len. Their default function prototypes are +as follows: + +

+ +
+static int hash (char *str, int len);
+int in_word_set (char *str, int len);
+
+ +

+By default, the generated hash function returns an integer value +created by adding len to several user-specified str key +positions indexed into an associated values table stored in a +local static array. The associated values table is constructed +internally by gperf and later output as a static local C array called +hash_table; its meaning and properties are described below. +See section 7 Implementation Details of GNU gperf. The relevant key positions are specified via the +`-k' option when running gperf, as detailed in the Options +section below. See section 4 Options to the gperf Utility. + +

+

+Two options, `-g' (assume you are compiling with GNU C and its +inline feature) and `-a' (assume ANSI C-style function +prototypes), alter the content of both the generated hash and +in_word_set routines. However, function in_word_set may +be modified more extensively, in response to your option settings. The +options that affect the in_word_set structure are: + +

+ +
    +
    + +
    `-t' +
    +Make use of the user-defined struct. + +
    `-S total switch statements' +
    +Generate 1 or more C 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. +
    +
+ +

+If the `-t' and `-S' options are omitted, the +default action is to generate a char * array containing the keys, +together with additional null 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. + +

+ + +

4 Options to the gperf Utility

+ +

+There are many options to gperf. They were added to make +the program more convenient for use with real applications. "On-line" +help is readily available via the `-h' option. Here is the complete +list of options. + +

+ + + +

4.1 Options that affect Interpretation of the Input File

+ + +
    +
    + +
    `-e keyword delimiter list' +
    +Allows the user to provide a string containing delimiters used to +separate keywords from their attributes. The default is ",\n". 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. + +
    `-t' +
    +Allows you to include a struct type declaration for generated +code. Any text before a pair of consecutive %% is consider part of the +type declaration. Key words 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, and G++, Pascal, and Modula 2 and 3 +reserved words are distributed with this release. +
    +
+ + + +

4.2 Options to specify the Language for the Output Code

+ + +
    +
    + +
    `-L generated language name' +
    +Instructs gperf to generate code in the language specified by the +option's argument. Languages handled are currently: + + +
      +
      + +
      `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 `const'. + +
      `C' +
      +Common C. This language is understood by ANSI C compilers, and also by +old-style C compilers, provided that you #define const to empty +for compilers which don't know about this keyword. + +
      `ANSI-C' +
      +ANSI C. This language is understood by ANSI C compilers and C++ compilers. + +
      `C++' +
      +C++. This language is understood by C++ compilers. +
      +
    + +The default is C. + +
    `-a' +
    +This option is supported for compatibility with previous releases of +gperf. It does not do anything. + +
    `-g' +
    +This option is supported for compatibility with previous releases of +gperf. It does not do anything. +
    +
+ + + +

4.3 Options for fine tuning Details in the Output Code

+ + +
    +
    + +
    `-K key name' +
    +This option is only useful when option `-t' has been given. +By default, the program assumes the structure component identifier for +the keyword is `name'. This option allows an arbitrary choice of +identifier for this component, although it still must occur as the first +field in your supplied struct. + +
    `-H hash function name' +
    +Allows you to specify the name for the generated hash function. Default +name is `hash'. This option permits the use of two hash tables in the +same file. + +
    `-N lookup function name' +
    +Allows you to specify the name for the generated lookup function. +Default name is `in_word_set'. This option permits completely automatic +generation of perfect hash functions, especially when multiple generated +hash functions are used in the same application. + +
    `-Z class name' +
    +This option is only useful when option `-L C++' has been given. +It allows you to specify the name of generated C++ class. Default name is +Perfect_Hash. + +
    `-7' +
    +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 (characters in the range 0..127). +(Note that the ANSI C functions isalnum and isgraph do +not guarantee that a character is in this range. Only an explicit +test like `c >= 'A' && c <= 'Z'' guarantees this.) This was the +default in earlier versions of gperf; now the default is to assume +8-bit characters. + +
    `-c' +
    +Generates C code that uses the strncmp function to perform +string comparisons. The default action is to use strcmp. + +
    `-C' +
    +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. + +
    `-E' +
    +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 <jjc@ai.mit.edu>. + +
    `-I' +
    +Include the necessary system include file, <string.h>, 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. + +
    `-G' +
    +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). + +
    `-W hash table array name' +
    +Allows you to specify the name for the generated array containing the +hash table. Default name is `wordlist'. This option permits the +use of two hash tables in the same file, even when the option `-G' +is given. + +
    `-S total switch statements' +
    +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 argument to this +option 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 +switch, etc. This is useful since many C compilers cannot +correctly generate code for large switch statements. This option +was inspired in part by Keith Bostic's original C program. + +
    `-T' +
    +Prevents the transfer of the type declaration to the output file. Use +this option if the type is already defined elsewhere. + +
    `-p' +
    +This option is supported for compatibility with previous releases of +gperf. It does not do anything. +
    +
+ + + +

4.4 Options for changing the Algorithms employed by gperf

+ + +
    +
    + +
    `-k keys' +
    +Allows selection of the character key positions used in the keywords' +hash function. The allowable choices range between 1-126, inclusive. +The positions are separated by commas, e.g., `-k 9,4,13,14'; +ranges may be used, e.g., `-k 2-7'; and positions may occur +in any order. Furthermore, the meta-character '*' causes the generated +hash function to consider all character positions in each key, +whereas '$' instructs the hash function to use the "final character" +of a key (this is the only way to use a character position greater than +126, incidentally). + +For instance, the option `-k 1,2,4,6-10,'$'' generates a hash +function that considers positions 1,2,4,6,7,8,9,10, plus the last +character in each key (which may differ for each key, obviously). Keys +with length less than the indicated key positions work properly, since +selected key positions exceeding the key length are simply not +referenced in the hash function. + +
    `-l' +
    +Compare key lengths before trying a string comparison. This might cut +down on the number of string comparisons made during the lookup, since +keys with different lengths are never compared via strcmp. +However, using `-l' might greatly increase the size of the +generated C code if the lookup table range is large (which implies that +the switch option `-S' is not enabled), since the length table +contains as many elements as there are entries in the lookup table. + +
    `-D' +
    +Handle keywords whose key position sets hash to duplicate values. +Duplicate hash values occur for two reasons: + + +
      +
    • + +Since gperf does not backtrack it is possible for it to process +all your input keywords without finding a unique mapping for each word. +However, frequently only a very small number of duplicates occur, and +the majority of keys still require one probe into the table. +
    • + +Sometimes a set of keys may have the same names, but possess different +attributes. With the -D option gperf treats all these keys as part of +an equivalence class and generates a perfect hash function with multiple +comparisons for duplicate keys. It is up to you to completely +disambiguate the keywords by modifying the generated C code. However, +gperf helps you out by organizing the output. +
    + +Option `-D' is extremely useful for certain large or highly +redundant keyword sets, e.g., assembler instruction opcodes. +Using this option usually means that the generated hash function is no +longer perfect. On the other hand, it permits gperf to work on +keyword sets that it otherwise could not handle. + +
    `-f iteration amount' +
    +Generate the perfect hash function "fast". This decreases gperf's +running time at the cost of minimizing generated table-size. The +iteration amount represents the number of times to iterate when +resolving a collision. `0' means iterate by the number of keywords. +This option is probably most useful when used in conjunction with options +`-D' and/or `-S' for large keyword sets. + +
    `-i initial value' +
    +Provides an initial 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 `-S' is used. Also, +`-i' is overriden when the `-r' option is used. + +
    `-j jump value' +
    +Affects the "jump value", i.e., how far to advance the +associated character value upon collisions. Jump value is rounded +up to an odd number, the default is 5. If the jump value is 0 +gperf jumps by random amounts. + +
    `-n' +
    +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. + +
    `-o' +
    +Reorders the keywords by sorting the keywords so that frequently +occuring key position set components appear first. A second reordering +pass follows so that keys with "already determined values" are placed +towards the front of the keylist. This may decrease the time required +to generate a perfect hash function for many keyword sets, and also +produce more minimal perfect hash functions. The reason for this is +that the reordering helps prune the search time by handling inevitable +collisions early in the search process. On the other hand, if the +number of keywords is very large using `-o' may +increase gperf's execution time, since collisions will begin +earlier and continue throughout the remainder of keyword processing. +See Cichelli's paper from the January 1980 Communications of the ACM for +details. + +
    `-r' +
    +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. If gperf has difficultly with a certain keyword set try using +`-r' or `-D'. + +
    `-s 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 keys. +If the size-multiple is negative the maximum associated value is +calculated by dividing it into the total number of keys. For +example, 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 -3 means "allow the maximum associated value to +be about 3 times smaller than the number of input keys". Negative +values are useful for limiting the overall size of the generated hash +table, though this usually increases the number of duplicate hash +values. + +If `generate switch' option `-S' is 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 keys (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. In particular, setting this value too high slows down +gperf's runtime, since it must search through a much larger range +of values. Judicious use of the `-f' option helps alleviate this +overhead, however. +
    +
+ + + +

4.5 Informative Output

+ + +
    +
    + +
    `-h' +
    +Prints a short summary on the meaning of each program option. Aborts +further program execution. + +
    `-v' +
    +Prints out the current version number. + +
    `-d' +
    +Enables the debugging option. This produces verbose diagnostics to +"standard error" when 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 `-d' +option is enabled. +
    +
+ + + +

5 Known Bugs and Limitations with gperf

+ +

+The following are some limitations with the current release of +gperf: + +

+ +
    +
  • + +The 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 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. + +However, since gperf does not backtrack no guaranteed solution +occurs on every run. On the other hand, it is usually easy to obtain a +solution by varying the option parameters. In particular, try the +`-r' option, and also try changing the default arguments to the +`-s' and `-j' options. To guarantee a solution, use +the `-D' and `-S' options, although the final results are not +likely to be a perfect hash function anymore! Finally, use the +`-f' option if you want gperf to generate the perfect hash +function fast, with less emphasis on making it minimal. + +
  • + +The size of the generate static keyword array can get 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 greatly inflates the object code size. If this +situation occurs, consider using the `-S' option to reduce data +size, potentially increasing keyword recognition time a negligible +amount. Since many C compilers cannot correctly generated code for +large switch statements it is important to qualify the -S option +with an appropriate numerical argument that controls the number of +switch statements generated. + +
  • + +The maximum number of key positions selected for a given key has an +arbitrary limit of 126. This restriction should be removed, and if +anyone considers this a problem write me and let me know so I can remove +the constraint. +
+ + + +

6 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: + +

+ +
    +
  • + +Make the algorithm more robust. At present, the program halts with an +error diagnostic if it can't find a direct solution and the `-D' +option is not enabled. A more comprehensive, albeit computationally +expensive, approach would employ backtracking or enable alternative +options and retry. It's not clear how helpful this would be, in +general, since most search sets are rather small in practice. + +
  • + +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). +Again, this is mostly of theoretical interest, since a sparse table +often produces faster lookups, and use of the `-S' switch +option can minimize the data size, at the expense of slightly longer +lookups (note that the gcc compiler generally produces good code for +switch statements, reducing the need for more complex schemes). + +
  • + +In addition to improving the algorithm, it would also be useful to +generate a C++ class or Ada package as the code output, in addition to +the current C routines. +
+ + + +

7 Implementation Details of GNU gperf

+ +

+A paper describing the high-level description of the data structures and +algorithms used to implement gperf will soon be available. This +paper is useful not only from a maintenance and enhancement perspective, +but also because they demonstrate several clever and useful programming +techniques, e.g., `Iteration Number' boolean arrays, double +hashing, a "safe" and efficient method for reading arbitrarily long +input from a file, and a provably optimal algorithm for simultaneously +determining both the minimum and maximum elements in a list. + +

+ + + +

8 Bibliography

+ +

+[1] Chang, C.C.: A Scheme for Constructing Ordered Minimal Perfect +Hashing Functions Information Sciences 39(1986), 187-195. + +[2] Cichelli, Richard J. 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. Minimal Perfect Hash Functions Made Simple +Communications of the ACM, 23, 1(January 1980), 17-19. + +[4] Cook, C. R. and Oldehoeft, R.R. 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. +Practical Perfect Hashing Computer Journal, 28, 1(January 1985), 54-58. + +[6] Jaeschke, G. 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. On Cichelli's Minimal Perfect +Hash Functions Method Communications of the ACM, 23, 12(December 1980), +728-729. + +

+

+[8] Sager, Thomas J. A Polynomial Time Generator for Minimal Perfect +Hash Functions Communications of the ACM, 28, 5(December 1985), 523-532 + +

+

+[9] Schmidt, Douglas C. GPERF: A Perfect Hash Function Generator +Second USENIX C++ Conference Proceedings, April 1990. + +

+

+[10] Sebesta, R.W. and Taylor, M.A. Minimal Perfect Hash Functions +for Reserved Word Lists SIGPLAN Notices, 20, 12(September 1985), 47-53. + +

+

+[11] Sprugnoli, R. Perfect Hashing Functions: A Single Probe +Retrieving Method for Static Sets Communications of the ACM, 20 +11(November 1977), 841-850. + +

+

+[12] Stallman, Richard M. Using and Porting GNU CC Free Software Foundation, +1988. + +

+

+[13] Stroustrup, Bjarne The C++ Programming Language. Addison-Wesley, 1986. + +

+

+[14] Tiemann, Michael D. User's Guide to GNU C++ Free Software +Foundation, 1989. + +

+


+This document was generated on 15 April 1998 using the +texi2html +translator version 1.51.

+ + diff --git a/doc/gperf.info b/doc/gperf.info new file mode 100644 index 0000000..4f9946f --- /dev/null +++ b/doc/gperf.info @@ -0,0 +1,1202 @@ +This is Info file gperf.info, produced by Makeinfo version 1.68 from +the input file gperf.texi. + +START-INFO-DIR-ENTRY +* Gperf: (gperf). Perfect Hash Function Generator. +END-INFO-DIR-ENTRY + + This file documents the features of the GNU Perfect Hash Function +Generator + + Copyright (C) 1989-1998 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 `gperf' General Public +License" and this permission notice may be included in translations +approved by the Free Software Foundation instead of in the original +English. + + +File: gperf.info, Node: Top, Next: Copying, Prev: (dir), Up: (dir) + +Introduction +************ + + This manual documents the GNU `gperf' perfect hash function generator +utility, focusing on its features and how to use them, and how to report +bugs. + +* Menu: + +* Copying:: GNU `gperf' General Public License says + how you can copy and share `gperf'. +* Contributors:: People who have contributed to `gperf'. +* Motivation:: Static search structures and GNU GPERF. +* Search Structures:: Static search structures and GNU `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. +* Implementation:: Implementation Details for GNU GPERF. +* Bibliography:: Material Referenced in this Report. + + -- The Detailed Node Listing -- + +High-Level Description of GNU `gperf' + +* Input Format:: Input Format to `gperf' +* Output Format:: Output Format for Generated C Code with `gperf' + +Input Format to `gperf' + +* Declarations:: `struct' Declarations and C Code Inclusion. +* Keywords:: Format for Keyword Entries. +* Functions:: Including Additional C Functions. + +Options to the `gperf' Utility + +* 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 `gperf' +* Verbosity:: Informative Output + + +File: gperf.info, Node: Copying, Next: Contributors, Prev: Top, Up: Top + +GNU GENERAL PUBLIC LICENSE +************************** + + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble +======== + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our 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. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, 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 a 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 tell them 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. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 1. This License Agreement 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 work + containing the Program or a portion of it, either verbatim or with + modifications. Each licensee is addressed as "you". + + 2. 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 General Public License + and to the absence of any warranty; and give any other recipients + of the Program a copy of this General Public License along with + the Program. You may charge a fee for the physical act of + transferring a copy. + + 3. You may modify your copy or copies of the Program or any portion of + it, and copy and distribute such modifications under the terms of + Paragraph 1 above, provided that you also do the following: + + * cause the modified files to carry prominent notices stating + that you changed the files and the date of any change; and + + * cause the whole of any work that you distribute or publish, + that in whole or in part contains the Program or any part + thereof, either with or without modifications, to be licensed + at no charge to all third parties under the terms of this + General Public License (except that you may choose to grant + warranty protection to some or all third parties, at your + option). + + * If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the simplest and most usual 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 General Public License. + + * 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. + + Mere aggregation of another independent work with the Program (or + its derivative) on a volume of a storage or distribution medium + does not bring the other work under the scope of these terms. + + 4. You may copy and distribute the Program (or a portion or + derivative of it, under Paragraph 2) in object code or executable + form under the terms of Paragraphs 1 and 2 above provided that you + also do one of the following: + + * accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + * accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal + charge for the cost of distribution) a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Paragraphs 1 and 2 above; or, + + * accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative + is allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + + Source code for a work means the preferred form of the work for + making modifications to it. For an executable file, complete + source code means all the source code for all modules it contains; + but, as a special exception, it need not include source code for + modules which are standard libraries that accompany the operating + system on which the executable file runs, or for standard header + files or definitions files that accompany that operating system. + + 5. You may not copy, modify, sublicense, distribute or transfer the + Program except as expressly provided under this General Public + License. Any attempt otherwise to copy, modify, sublicense, + distribute or transfer the Program is void, and will automatically + terminate your rights to use the Program under this License. + However, parties who have received copies, or rights to use + copies, from you under this General Public License will not have + their licenses terminated so long as such parties remain in full + compliance. + + 6. By copying, distributing or modifying 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. + + 7. 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. + + 8. 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 the 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 the license, you may choose + any version ever published by the Free Software Foundation. + + 9. 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 + + 10. 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. + + 11. 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 humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) 19YY NAME OF AUTHOR + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, 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) 19YY NAME OF AUTHOR + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + + You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the program, +if necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + SIGNATURE OF TY COON, 1 April 1989 + Ty Coon, President of Vice + + That's all there is to it! + + +File: gperf.info, Node: Contributors, Next: Motivation, Prev: Copying, Up: Top + +Contributors to GNU `gperf' Utility +*********************************** + + * The GNU `gperf' perfect hash function generator utility was + originally written in GNU C++ by Douglas C. Schmidt. It is now + also available in a highly-portable "old-style" C version. 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 + `' and `'. + + * 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 `gperf'. + + +File: gperf.info, Node: Motivation, Next: Search Structures, Prev: Contributors, Up: Top + +Introduction +************ + + `gperf' is a perfect hash function generator written in C++. It +transforms an N element user-specified keyword set W into a perfect +hash function F. F uniquely maps keywords in W onto the range 0..K, +where K >= N. If K = N then F is a *minimal* perfect hash function. +`gperf' generates a 0..K element static lookup table and a pair of C +functions. These functions determine whether a given character string +S occurs in W, using at most one probe into the lookup table. + + `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 Pascal, GNU +Modula 3, and GNU indent. Complete C++ source code for `gperf' is +available via anonymous ftp from `ics.uci.edu' and `ftp.santafe.edu'. +`gperf' was also distributed along with the GNU libg++ library for +several years. A highly portable, functionally equivalent K&R C +version of `gperf' is archived in comp.sources.unix, volume 20. +Finally, a paper describing `gperf''s design and implementation in +greater detail is available in the Second USENIX C++ Conference +proceedings. + + +File: gperf.info, Node: Search Structures, Next: Description, Prev: Motivation, Up: Top + +Static search structures and GNU `gperf' +**************************************** + + A "static search structure" is an Abstract Data Type with certain +fundamental operations, e.g., *initialize*, *insert*, and *retrieve*. +Conceptually, all insertions occur before any retrievals. In practice, +`gperf' generates a `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 *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 "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 N element +sorted array is space efficient, though the average-case time +complexity for retrieval operations using binary search is proportional +to log 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. + + *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: + + * It allows keyword recognition in a static search set using at most + *one* probe into the hash table. This represents the "perfect" + property. + + * The actual memory allocated to store the keywords is precisely + large enough for the keyword set, and *no larger*. This is the + "minimal" property. + + For most applications it is far easier to generate *perfect* hash +functions than *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. `gperf''s default behavior generates +*near-minimal* perfect hash functions for keyword sets. However, +`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 *once*, if it subsequently +receives heavy use multiple times. `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 `gperf' is currently used in +several production and research compilers, including GNU C, GNU C++, +GNU Pascal, and GNU Modula 3. The latter two compilers are not yet +part of the official GNU distribution. Each compiler utilizes `gperf' +to automatically generate static search structures that efficiently +identify their respective reserved keywords. + + +File: gperf.info, Node: Description, Next: Options, Prev: Search Structures, Up: Top + +High-Level Description of GNU `gperf' +************************************* + +* Menu: + +* Input Format:: Input Format to `gperf' +* Output Format:: Output Format for Generated C Code with `gperf' + + The perfect hash function generator `gperf' reads a set of +"keywords" from a "keyfile" (or from the standard input by default). +It attempts to derive a perfect hashing function that recognizes a +member of the "static keyword set" with at most a single probe into the +lookup table. If `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 `gperf'. + + By default, `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 `gperf' to utilize a C `switch' statement +scheme that minimizes data space storage size. Furthermore, using a C +`switch' may actually speed up the keyword retrieval time somewhat. +Actual results depend on your C compiler, of course. + + In general, `gperf' assigns values to the characters 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 `gperf' to find and generate a perfect hash function. +Experimentation is the key to getting the most from `gperf'. + + +File: gperf.info, Node: Input Format, Next: Output Format, Prev: Description, Up: Description + +Input Format to `gperf' +======================= + + You can control the input keyfile format by varying certain +command-line arguments, in particular the `-t' option. The input's +appearance is similar to GNU utilities `flex' and `bison' (or UNIX +utilities `lex' and `yacc'). Here's an outline of the general format: + + declarations + %% + keywords + %% + functions + + *Unlike* `flex' or `bison', all sections of `gperf''s input are +optional. The following sections describe the input format for each +section. + +* Menu: + +* Declarations:: `struct' Declarations and C Code Inclusion. +* Keywords:: Format for Keyword Entries. +* Functions:: Including Additional C Functions. + + +File: gperf.info, Node: Declarations, Next: Keywords, Prev: Input Format, Up: Input Format + +`struct' Declarations and C Code Inclusion +------------------------------------------ + + The keyword input file optionally contains a section for including +arbitrary C declarations and definitions, as well as provisions for +providing a user-supplied `struct'. If the `-t' option *is* enabled, +you *must* provide a C `struct' as the last component in the +declaration section from the keyfile file. The first field in this +struct must be a `char *' identifier called `name', although it is +possible to modify this field's name with the `-K' option described +below. + + Here is simple example, using months of the year and their +attributes as input: + + struct months { 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 + + Separating the `struct' declaration from the list of key words and +other fields are a pair of consecutive percent signs, `%%', appearing +left justified in the first column, as in the UNIX utility `lex'. + + Using a syntax similar to GNU utilities `flex' and `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 `%{', `%}' pairs. Here is an input +fragment based on the previous example that illustrates this feature: + + %{ + #include + /* This section of code is inserted directly into the output. */ + int return_month_days (struct months *months, int is_leap_year); + %} + struct months { char *name; int number; int days; int leap_days; }; + %% + january, 1, 31, 31 + february, 2, 28, 29 + march, 3, 31, 31 + ... + + It is possible to omit the declaration section entirely. In this +case the keyfile begins directly with the first keyword line, e.g.: + + january, 1, 31, 31 + february, 2, 28, 29 + march, 3, 31, 31 + april, 4, 30, 30 + ... + + +File: gperf.info, Node: Keywords, Next: Functions, Prev: Declarations, Up: Input Format + +Format for Keyword Entries +-------------------------- + + The second keyfile format section contains lines of keywords and any +associated attributes you might supply. A line beginning with `#' in +the first column is considered a comment. Everything following the `#' +is ignored, up to and including the following newline. + + The first field of each non-comment line is always the key itself. +It should be given as a simple name, i.e., without surrounding string +quotation marks, and be left-justified flush against the first column. +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: + + # 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 + + Note that unlike `flex' or `bison' the first `%%' 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 `struct' provided by you in the +declaration section. If the `-t' option is *not* enabled these fields +are simply ignored. All previous examples except the last one contain +keyword attributes. + + +File: gperf.info, Node: Functions, Prev: Keywords, Up: Input Format + +Including Additional C Functions +-------------------------------- + + The optional third section also corresponds closely with conventions +found in `flex' and `bison'. All text in this section, starting at the +final `%%' 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. + + +File: gperf.info, Node: Output Format, Prev: Input Format, Up: Description + +Output Format for Generated C Code with `gperf' +=============================================== + + Several options control how the generated C code appears on the +standard output. Two C function are generated. They are called `hash' +and `in_word_set', although you may modify the name for `in_word_set' +with a command-line option. Both functions require two arguments, a +string, `char *' STR, and a length parameter, `int' LEN. Their default +function prototypes are as follows: + + static int hash (char *str, int len); + int in_word_set (char *str, int len); + + By default, the generated `hash' function returns an integer value +created by adding LEN to several user-specified STR key positions +indexed into an "associated values" table stored in a local static +array. The associated values table is constructed internally by +`gperf' and later output as a static local C array called HASH_TABLE; +its meaning and properties are described below. *Note +Implementation::. The relevant key positions are specified via the `-k' +option when running `gperf', as detailed in the *Options* section +below. *Note Options::. + + Two options, `-g' (assume you are compiling with GNU C and its +`inline' feature) and `-a' (assume ANSI C-style function prototypes), +alter the content of both the generated `hash' and `in_word_set' +routines. However, function `in_word_set' may be modified more +extensively, in response to your option settings. The options that +affect the `in_word_set' structure are: + + `-t' + Make use of the user-defined `struct'. + + `-S TOTAL SWITCH STATEMENTS' + Generate 1 or more C `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. + + If the `-t' and `-S' options are omitted, the default action is to +generate a `char *' array containing the keys, together with additional +null 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. + + +File: gperf.info, Node: Options, Next: Input Details, Prev: Description, Up: Top + +Options to the `gperf' Utility +****************************** + + There are *many* options to `gperf'. They were added to make the +program more convenient for use with real applications. "On-line" help +is readily available via the `-h' option. Here is the complete list of +options. + +* Menu: + +* 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 `gperf' +* Verbosity:: Informative Output + + +File: gperf.info, Node: Input Details, Next: Output Language, Prev: Options, Up: Options + +Options that affect Interpretation of the Input File +==================================================== + + `-e KEYWORD DELIMITER LIST' + Allows the user to provide a string containing delimiters + used to separate keywords from their attributes. The default + is ",\n". 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. + + `-t' + Allows you to include a `struct' type declaration for + generated code. Any text before a pair of consecutive %% is + consider part of the type declaration. Key words 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, and G++, Pascal, and Modula 2 and 3 + reserved words are distributed with this release. + + +File: gperf.info, Node: Output Language, Next: Output Details, Prev: Input Details, Up: Options + +Options to specify the Language for the Output Code +=================================================== + + `-L GENERATED LANGUAGE NAME' + Instructs `gperf' to generate code in the language specified + by the option's argument. Languages handled are currently: + + `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 `const'. + + `C' + Common C. This language is understood by ANSI C + compilers, and also by old-style C compilers, + provided that you `#define const' to empty for + compilers which don't know about this keyword. + + `ANSI-C' + ANSI C. This language is understood by ANSI C + compilers and C++ compilers. + + `C++' + C++. This language is understood by C++ compilers. + + The default is C. + + `-a' + This option is supported for compatibility with previous + releases of `gperf'. It does not do anything. + + `-g' + This option is supported for compatibility with previous + releases of `gperf'. It does not do anything. + + +File: gperf.info, Node: Output Details, Next: Algorithmic Details, Prev: Output Language, Up: Options + +Options for fine tuning Details in the Output Code +================================================== + + `-K KEY NAME' + This option is only useful when option `-t' has been given. + By default, the program assumes the structure component + identifier for the keyword is `name'. This option allows an + arbitrary choice of identifier for this component, although + it still must occur as the first field in your supplied + `struct'. + + `-H HASH FUNCTION NAME' + Allows you to specify the name for the generated hash + function. Default name is `hash'. This option permits the + use of two hash tables in the same file. + + `-N LOOKUP FUNCTION NAME' + Allows you to specify the name for the generated lookup + function. Default name is `in_word_set'. This option + permits completely automatic generation of perfect hash + functions, especially when multiple generated hash functions + are used in the same application. + + `-Z CLASS NAME' + This option is only useful when option `-L C++' has been + given. It allows you to specify the name of generated C++ + class. Default name is `Perfect_Hash'. + + `-7' + 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 + (characters in the range 0..127). (Note that the ANSI C + functions `isalnum' and `isgraph' do *not* guarantee that a + character is in this range. Only an explicit test like `c >= + 'A' && c <= 'Z'' guarantees this.) This was the default in + earlier versions of `gperf'; now the default is to assume + 8-bit characters. + + `-c' + Generates C code that uses the `strncmp' function to perform + string comparisons. The default action is to use `strcmp'. + + `-C' + 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. + + `-E' + 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 `'. + + `-I' + Include the necessary system include file, `', 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. + + `-G' + 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). + + `-W HASH TABLE ARRAY NAME' + Allows you to specify the name for the generated array + containing the hash table. Default name is `wordlist'. This + option permits the use of two hash tables in the same file, + even when the option `-G' is given. + + `-S TOTAL SWITCH STATEMENTS' + 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 argument to this option 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 `switch', etc. This + is useful since many C compilers cannot correctly generate + code for large `switch' statements. This option was inspired + in part by Keith Bostic's original C program. + + `-T' + Prevents the transfer of the type declaration to the output + file. Use this option if the type is already defined + elsewhere. + + `-p' + This option is supported for compatibility with previous + releases of `gperf'. It does not do anything. + + +File: gperf.info, Node: Algorithmic Details, Next: Verbosity, Prev: Output Details, Up: Options + +Options for changing the Algorithms employed by `gperf' +======================================================= + + `-k KEYS' + Allows selection of the character key positions used in the + keywords' hash function. The allowable choices range between + 1-126, inclusive. The positions are separated by commas, + e.g., `-k 9,4,13,14'; ranges may be used, e.g., `-k 2-7'; and + positions may occur in any order. Furthermore, the + meta-character '*' causes the generated hash function to + consider *all* character positions in each key, whereas '$' + instructs the hash function to use the "final character" of a + key (this is the only way to use a character position greater + than 126, incidentally). + + For instance, the option `-k 1,2,4,6-10,'$'' generates a hash + function that considers positions 1,2,4,6,7,8,9,10, plus the + last character in each key (which may differ for each key, + obviously). Keys with length less than the indicated key + positions work properly, since selected key positions + exceeding the key length are simply not referenced in the + hash function. + + `-l' + Compare key lengths before trying a string comparison. This + might cut down on the number of string comparisons made + during the lookup, since keys with different lengths are + never compared via `strcmp'. However, using `-l' might + greatly increase the size of the generated C code if the + lookup table range is large (which implies that the switch + option `-S' is not enabled), since the length table contains + as many elements as there are entries in the lookup table. + + `-D' + Handle keywords whose key position sets hash to duplicate + values. Duplicate hash values occur for two reasons: + + * Since `gperf' does not backtrack it is possible for it + to process all your input keywords without finding a + unique mapping for each word. However, frequently only + a very small number of duplicates occur, and the + majority of keys still require one probe into the table. + + * Sometimes a set of keys may have the same names, but + possess different attributes. With the -D option + `gperf' treats all these keys as part of an equivalence + class and generates a perfect hash function with multiple + comparisons for duplicate keys. It is up to you to + completely disambiguate the keywords by modifying the + generated C code. However, `gperf' helps you out by + organizing the output. + + Option `-D' is extremely useful for certain large or highly + redundant keyword sets, e.g., assembler instruction opcodes. + Using this option usually means that the generated hash + function is no longer perfect. On the other hand, it permits + `gperf' to work on keyword sets that it otherwise could not + handle. + + `-f ITERATION AMOUNT' + Generate the perfect hash function "fast". This decreases + `gperf''s running time at the cost of minimizing generated + table-size. The iteration amount represents the number of + times to iterate when resolving a collision. `0' means + iterate by the number of keywords. This option is probably + most useful when used in conjunction with options `-D' and/or + `-S' for *large* keyword sets. + + `-i INITIAL VALUE' + Provides an initial 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 `-S' is used. Also, `-i' is overriden when the + `-r' option is used. + + `-j JUMP VALUE' + Affects the "jump value", i.e., how far to advance the + associated character value upon collisions. JUMP VALUE is + rounded up to an odd number, the default is 5. If the JUMP + VALUE is 0 `gperf' jumps by random amounts. + + `-n' + 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. + + `-o' + Reorders the keywords by sorting the keywords so that + frequently occuring key position set components appear first. + A second reordering pass follows so that keys with "already + determined values" are placed towards the front of the + keylist. This may decrease the time required to generate a + perfect hash function for many keyword sets, and also produce + more minimal perfect hash functions. The reason for this is + that the reordering helps prune the search time by handling + inevitable collisions early in the search process. On the + other hand, if the number of keywords is *very* large using + `-o' may *increase* `gperf''s execution time, since + collisions will begin earlier and continue throughout the + remainder of keyword processing. See Cichelli's paper from + the January 1980 Communications of the ACM for details. + + `-r' + 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. If `gperf' has + difficultly with a certain keyword set try using `-r' or `-D'. + + `-s 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 keys. If the SIZE-MULTIPLE is + negative the maximum associated value is calculated by + *dividing* it into the total number of keys. For example, 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 -3 means "allow the maximum associated + value to be about 3 times smaller than the number of input + keys". Negative values are useful for limiting the overall + size of the generated hash table, though this usually + increases the number of duplicate hash values. + + If `generate switch' option `-S' is *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 keys (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. In + particular, setting this value too high slows down `gperf''s + runtime, since it must search through a much larger range of + values. Judicious use of the `-f' option helps alleviate this + overhead, however. + + +File: gperf.info, Node: Verbosity, Next: Bugs, Prev: Algorithmic Details, Up: Options + +Informative Output +================== + + `-h' + Prints a short summary on the meaning of each program option. + Aborts further program execution. + + `-v' + Prints out the current version number. + + `-d' + Enables the debugging option. This produces verbose + diagnostics to "standard error" when `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 `-d' + option is enabled. + + +File: gperf.info, Node: Bugs, Next: Projects, Prev: Verbosity, Up: Top + +Known Bugs and Limitations with `gperf' +*************************************** + + The following are some limitations with the current release of +`gperf': + + * The `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 + `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. + + However, since `gperf' does not backtrack no guaranteed solution + occurs on every run. On the other hand, it is usually easy to + obtain a solution by varying the option parameters. In + particular, try the `-r' option, and also try changing the default + arguments to the `-s' and `-j' options. To *guarantee* a + solution, use the `-D' and `-S' options, although the final + results are not likely to be a *perfect* hash function anymore! + Finally, use the `-f' option if you want `gperf' to generate the + perfect hash function *fast*, with less emphasis on making it + minimal. + + * The size of the generate static keyword array can get *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 *greatly* inflates the object code size. If + this situation occurs, consider using the `-S' option to reduce + data size, potentially increasing keyword recognition time a + negligible amount. Since many C compilers cannot correctly + generated code for large switch statements it is important to + qualify the -S option with an appropriate numerical argument that + controls the number of switch statements generated. + + * The maximum number of key positions selected for a given key has an + arbitrary limit of 126. This restriction should be removed, and if + anyone considers this a problem write me and let me know so I can + remove the constraint. + + +File: gperf.info, Node: Projects, Next: Implementation, Prev: Bugs, Up: Top + +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: + + * Make the algorithm more robust. At present, the program halts + with an error diagnostic if it can't find a direct solution and + the `-D' option is not enabled. A more comprehensive, albeit + computationally expensive, approach would employ backtracking or + enable alternative options and retry. It's not clear how helpful + this would be, in general, since most search sets are rather small + in practice. + + * 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). Again, this is mostly of theoretical interest, since a + sparse table often produces faster lookups, and use of the `-S' + `switch' option can minimize the data size, at the expense of + slightly longer lookups (note that the gcc compiler generally + produces good code for `switch' statements, reducing the need for + more complex schemes). + + * In addition to improving the algorithm, it would also be useful to + generate a C++ class or Ada package as the code output, in + addition to the current C routines. + + +File: gperf.info, Node: Implementation, Next: Bibliography, Prev: Projects, Up: Top + +Implementation Details of GNU `gperf' +************************************* + + A paper describing the high-level description of the data structures +and algorithms used to implement `gperf' will soon be available. This +paper is useful not only from a maintenance and enhancement perspective, +but also because they demonstrate several clever and useful programming +techniques, e.g., `Iteration Number' boolean arrays, double hashing, a +"safe" and efficient method for reading arbitrarily long input from a +file, and a provably optimal algorithm for simultaneously determining +both the minimum and maximum elements in a list. + + +File: gperf.info, Node: Bibliography, Prev: Implementation, Up: Top + +Bibliography +************ + + [1] Chang, C.C.: A Scheme for Constructing Ordered Minimal Perfect +Hashing Functions Information Sciences 39(1986), 187-195. + + [2] Cichelli, Richard J. 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. Minimal Perfect Hash Functions Made Simple +Communications of the ACM, 23, 1(January 1980), 17-19. + + [4] Cook, C. R. and Oldehoeft, R.R. 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. +Practical Perfect Hashing Computer Journal, 28, 1(January 1985), 54-58. + + [6] Jaeschke, G. 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. On Cichelli's Minimal Perfect +Hash Functions Method Communications of the ACM, 23, 12(December 1980), +728-729. + + [8] Sager, Thomas J. A Polynomial Time Generator for Minimal Perfect +Hash Functions Communications of the ACM, 28, 5(December 1985), 523-532 + + [9] Schmidt, Douglas C. GPERF: A Perfect Hash Function Generator +Second USENIX C++ Conference Proceedings, April 1990. + + [10] Sebesta, R.W. and Taylor, M.A. Minimal Perfect Hash Functions +for Reserved Word Lists SIGPLAN Notices, 20, 12(September 1985), 47-53. + + [11] Sprugnoli, R. Perfect Hashing Functions: A Single Probe +Retrieving Method for Static Sets Communications of the ACM, 20 +11(November 1977), 841-850. + + [12] Stallman, Richard M. Using and Porting GNU CC Free Software +Foundation, 1988. + + [13] Stroustrup, Bjarne The C++ Programming Language. +Addison-Wesley, 1986. + + [14] Tiemann, Michael D. User's Guide to GNU C++ Free Software +Foundation, 1989. + + + +Tag Table: +Node: Top1228 +Node: Copying2845 +Node: Contributors16148 +Node: Motivation17279 +Node: Search Structures18560 +Node: Description22105 +Node: Input Format23925 +Node: Declarations24720 +Node: Keywords27025 +Node: Functions28614 +Node: Output Format29108 +Node: Options31474 +Node: Input Details32192 +Node: Output Language33268 +Node: Output Details34742 +Node: Algorithmic Details39066 +Node: Verbosity46861 +Node: Bugs47612 +Node: Projects49842 +Node: Implementation51419 +Node: Bibliography52136 + +End Tag Table diff --git a/doc/gperf.ps b/doc/gperf.ps new file mode 100644 index 0000000..0a7bf0d --- /dev/null +++ b/doc/gperf.ps @@ -0,0 +1,2883 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: gperf.dvi +%%Pages: 36 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o gperf.ps gperf.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1998.05.02:1318 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (gperf.dvi) +@start /Fa 1 47 df<120FEA3FC0127FA212FFA31380EA7F00123C0A0A77891C>46 +D E /Fb 1 47 df<13FCEA03FF000F13804813C05AA25AA2B5FCA31480A214006C5A6C5A +6C5AEA0FE0121271912B>46 D E /Fc 2 109 df97 +D<13FFB5FCA512077EB3B3AFB512FCA5163F7EBE19>108 D E /Fd +5 118 df99 D114 +D<903907FF80F0017FEBF1F848B512FD000714FF5A5A5AEBFC00D87FE0131F0180130F48 +C71207481403A5007FEC01F001C090C7FCEA3FF013FE381FFFF86CEBFFC0000314F8C614 +FF013F1480010714E0D9003F13F0020013F8ED0FFC1503003CEC01FE007E140000FE15FF +167F7EA37F6D14FF16FE01F013036DEB07FC01FF137F91B512F816F016E04815C0D8FC3F +1400010F13FCD8780113E0283278B038>III E /Fe 28 122 df46 D<15F014011407141F147FEB03FF137FB6FCA313FC1380C7FC +B3B3B2007FB712E0A52B4777C63D>49 DII65 D<93261FFF80EB01C00307B500F81303033F02FE13074A +B7EAC00F0207EEE03F021F903AFE007FF87F027F01E0903807FCFF91B5C70001B5FC0103 +01FC6E7E4901F0151F4901C0814949814990C97E494882494882485B48197F4A173F5A4A +171F5A5C48190FA2485B1A07A25AA297C7FC91CDFCA2B5FCAD7EA280A2F207C07EA36C7F +A26C190F6E18807E6E171F6C1A006E5F6C193E6C6D177E6D6C5F6D6C4C5A6D6D15036D6D +4B5A6D01F04B5A6D01FCED3FC0010001FFEDFF806E01E0D903FEC7FC021F01FEEB3FFC02 +0790B612F002015EDA003F92C8FC030714FCDB001F13804A4D79CB59>67 +DII< +BBFCA41A80D8001F01C0C7FC181F18038484197F193F191F1AC0190FA31907A4171FF103 +E0A496C7FCA25FA25F5F5E160792B6FCA5EDC0071601828383A283A794C9FCB1B8FCA543 +4A7CC94D>I73 +D75 +D97 D<91380FFF8091B512F801 +0314FF010F15804948C613C0D97FF8EB1FE0D9FFE0EB3FF04849137F4849EBFFF84890C7 +FCA2485A121FA24848EC7FF0EE3FE0EE1FC0007F92C7FC5BA212FFAC127FA27FA2123FA2 +6C6C153EA26C6C157E177C6C6D14FC6C6D14F86C6D13036C6DEB07F0D97FFCEB1FE06DB4 +EBFFC0010F90B5120001035C010014F0020F13802F347CB237>99 +DIIII<13FCEA03FF487F487FA2487FA66C5BA26C5B6C90C7FCEA +00FC90C8FCABEB7FC0B5FCA512037EB3B3A2B61280A5194D7BCC22>105 +D108 D<90287FC001FFC0EC7F +F0B5010F01FC0103B5FC033F6D010F804B6D4980DBFE079026803F817F9126C1F801903A +C07E007FF00003D9C3E0DAE0F8806C9026C78000D9F1E06D7E02CFC7EBF3C002DEEDF780 +DD7FFF6E7E02FC93C7FC4A5DA24A5DA34A5DB3AAB6D8C03FB5D8F00FB512FCA55E327BB1 +67>I<903A7FC001FFC0B5010F13F8033F7F4B13FFDBFE077F9138C1F00300039026C3E0 +017F6CD9C78080ECCF0014DE02DC6D7F14FC5CA25CA35CB3AAB6D8C07FEBFFE0A53B327B +B144>I<913807FF80027F13F80103B6FC010F15C090261FFE017F903A7FF0003FF84948 +6D7E480180EB07FE4890C76C7E4817804980000F17C048486E13E0A2003F17F0A249157F +007F17F8A400FF17FCAB007F17F8A46C6CEDFFF0A2001F17E0A26C6C4A13C0A26C6C4A13 +806C6D4913006C5E6C01E0EB1FFC6D6C495A903A3FFE01FFF0010FB612C0010392C7FCD9 +007F13F80207138036347DB23D>I<9039FF803FE0B5EBFFF8028113FE02837FDA87E113 +80EC8F830003D99F0713C06C139E14BCA214F8A24A6C13806F13006F5A4A90C7FCA45CB3 +A8B612E0A52A327CB132>114 D<903907FF8070017FEBF1F048B6FC1207380FFC01391F +E0003F4848130F491307127F90C71203A2481401A27FA27F01F090C7FC13FCEBFFC06C13 +FEECFFE06C14FC6C806CECFF806C15C06C15E06C15F06C7E011F14F8010114FCEB000FEC +007FED1FFE0078140F00F8140715037E1501A27E16FC7E15036D14F86D13076D14F001F8 +EB1FE001FFEBFFC04890B51280486C1400D8F81F13FCD8E00313C027347CB230>I<14F8 +A51301A41303A21307A2130FA2131F133F137F13FF1203000F90B512F0B7FCA426007FF8 +C7FCB3A7167CAA013F14F880A290391FFE01F0010F1303903907FF87E06DEBFFC06D1480 +6D6C1300EC0FFC26467EC430>II119 D<007FB500C090387FFFE0A5C601F0C73803F8006E5D017F5E6E1407 +013F5E80170F011F5E6E141F6D93C7FC6F5B6D153E6F137E6D157C6F13FCA26D6D5B1601 +6D5DEDF803027F5CEDFC07023F5CEDFE0F021F5C15FF161F6E91C8FC16BF6E13BE16FE6E +5BA26E5BA36E5BA26F5AA26F5AA26F5AA393C9FC5D153E157E157CD81F8013FC486C5B38 +7FE001D8FFF05B14035D14074A5A49485A007F133F4948CAFC383F81FE381FFFF86C5B6C +13C0C648CBFC3B477EB041>121 D E /Ff 5 115 df101 D<923801FFC0030F13F0033F13FC92B512FE5C4A14FF5C4A1303 +EC1FF89238F001FEEC3FE09238C000FC027F14005DAA003FB712F05AB812F8A36C16F0A2 +C7D87F80C7FCB3B3003FB7FCA2481680A36C1600A2304A7CC93E>II +112 D114 D +E /Fg 5 115 df101 D<4CB47E041F13F093B512FC03 +0380030F805D4B15805D92B7FC4AEBFC074A13F0DCC00313004A13804C6C5A4A48EB0078 +95C7FC5DAB003FB812F04883B97EA56C5F6C5FC7D80FFCC9FCB3B3A8001FB712FE488248 +83A56C94C7FC6C5E39597BD84A>II112 D114 +D E /Fh 50 123 df +12 D<39078003C0391FE00FF0003F131F01F013F8A6390F3007980000EB001801701338 +01601330A201E01370491360A2000114E039038001C001001380481303000EEB0700000C +1306001C130E485B485B485B4813601D1C75BE2D>34 D39 D<007FB5FCA2B512FEA418067C961E>45 D<121EEA3F80EA7FC012FFA41380EA7F00 +123C0A0A788919>I<13F0EA01FC1203EA07FEA313FCA2EA03F8EA01E0C7FCB3121EEA3F +80EA7FC012FFA41380EA7F00123C0F2778A619>58 D<000FB912FE5AA27ECDFCAE007FB9 +12F0BAFCA27E3F1679A147>61 D<17E016011603831607A2160FA2161F83163FA2167F16 +7716F7EEE7FCED01E316C3150316831507EE03FEED0F01150E151E151C153C03387FED78 +00157015F05D4A4880177F4A5AA24AC7FCA2020E81173F5C021FB6FC5CA20270C7EA3FE0 +171F5CA2495AA2494881170F49C8FCA2130EA24982013C1507A2137CD801FE4B7E2607FF +80EC3FFEB500F00107B512FC19F85E3E417DC044>65 D67 D<013FB812F8A39026007FF0C7127F6E48140F18034B14011800A3 +1978147F4B1570A502FF143892C7FCA3190017784915704A14F016011603160F91B6FC49 +5DA29138FC001F16071603160101075D5CA2197019F019E0010F4A5A4A90C7120119C0A2 +18031980011F16075CF00F00A260181E013F163E4A157E4D5A1703017F150F01FFEDFFF8 +B9FCA2603D3E7DBD3E>69 D<013FB812E0A3903A007FF000016E48EB003F180F4B140718 +03A31801147F4B15C0A514FF92C71270A395C7FC17F0495D5C160116031607161F49B65A +A39138FC003F160F160701075D4A1303A5010F4AC8FC5C93C9FCA4131F5CA5133F5CA313 +7FEBFFF0B612F8A33B3E7DBD3B>I<4BB46C1370031F01F013F0037F9038FC01E0913A03 +FF807E03913A0FF8000F83DA1FE0EB07C7DA7F80EB01EF4AC812FFD903FE16C04948157F +4948153F495A4948151F495A4948168091C9120F5A485AA2485A000F18004982121FA248 +485EA295C7FC485AA412FF5BA6043FB512E05BA29339001FFC00715AA2607F127FA2171F +123F6D5EA2121F7F000F163F6C7E6C6C4B5A7F6C6C15FF6C6DEB01EFD93FC0EB07C7D91F +F0EB1F87D907FE9038FE03800101B5EAF8016D6C01E0C8FCDA07FEC9FC3C4276BF47>I< +013FB5D8F807B6FC04F015FEA29026007FF0C7380FFE006E486E5AA24B5DA4180F147F4B +5DA4181F14FF92C85BA4183F5B4A5EA491B8FC5B6102FCC8127FA318FF13074A93C7FCA4 +5F130F4A5DA41703131F4A5DA41707133F4A5DA3017F150F496C4A7EB6D8E01FB512FC61 +15C0483E7DBD44>I<021FB512FCA3DA000713006F5AA25EA41507A25EA4150FA25EA415 +1FA25EA4153FA25EA4157FA25EA415FFA293C7FCA45C121FD87F805BEAFFC0A214035D13 +804A5AEAFE0000F8495A48495A00705C6C495A6C01FEC8FC380F81FC3803FFE0C690C9FC +2E407ABD2F>74 D<013FB512FEA25E9026007FF8C8FCEC3FE0A25DA5147F5DA514FF92C9 +FCA55B5CA513035CA513075CA21838A21870130F5CA218E0A3011F15014A15C01703A217 +07EF0F80013F151F4A143F177FEFFF00017F140301FF143FB9FC5FA2353E7DBD39>76 +D<90263FFFF0933807FFFE5013FC629026007FF8EFFC00023F4D5AA2023BEF77F0A2DA39 +FC16E7A2F101CF0279EE038FDA70FE5FF1070FA2190E1A1FDAF07F151C02E06019381970 +6F7EF1E03F130102C0DB01C05BA26F6CEB0380A2953807007F0103160E4A6C6C93C7FC60 +A2606201076D6C5B02005F60A26F6C485A94380380015B010EDB07005BA2923801FC0EA2 +4D1303131E011C6D6C485C5FA25F1907013CEC7FC0013860013C5D137C01FE6EC7120F26 +07FF80013E4A7EB500FC031FB512F8043C5E4A131C573E7DBD53>I<90263FFFE0023FB5 +FC6F16FEA29026003FF8020313C0021F030013004A6C157C023B163C6F15381439810238 +167802787FDA707F157082153F82031F15F002F07FDAE00F5D8215078203031401010180 +DAC0015D82811780047F1303010315C04A013F5C17E0161F17F0040F1307010715F891C7 +000791C7FC17FC160317FE04015B4915FF010E6E130E188E177F18CEEF3FDE011E16FE01 +1C6F5AA2170FA21707133C01386F5A133C017C150113FE2607FF801400B512FC18705C48 +3E7DBD44>I<923803FF80031F13F09238FE01FE913903F0003FDA0FC0EB1FC0DA3F80EB +07E0027EC76C7E49486E7E49488149486E7E4948157F495A013F17804948ED3FC049C9FC +A24848EE1FE012035B000718F05B120FA2485A19F8123F5BA2127FA219F04848163FA5F0 +7FE0A35BF0FFC0A219805F19007F4D5A127F4D5A60003F160F6D5E001F4C5A4D5A6C6C4B +5A95C7FC6C6C15FE00034B5A6C6C4A5A6C6C4A5A017FEC1FC06D6C495AD90FE001FEC8FC +903903F807F80100B512C0DA0FFCC9FC3D4276BF47>I<013FB612FEEFFFE018F8903B00 +7FF0000FFC6E48EB01FF7113804BEC7FC0183F19E0F01FF0A2147F5D19F8A402FFED3FF0 +92C8FCA219E0A2F07FC05B4AEDFF8019004D5A4D5AEF0FF80103ED3FE04A903801FF8091 +B648C7FC17F002FCCAFCA213075CA5130F5CA5131F5CA5133F5CA3137F497EB612E0A25D +3D3E7DBD3E>I<013FB612F017FF18E0903B007FF0003FF86E48EB07FCEF01FE4B6D7EF0 +7F8019C0183F19E0147F4B15F0A502FFED7FE092C8FCA219C0F0FF80A2494B13004A5D4D +5AEF0FF04D5AEF7F800103DA07FEC7FC91B612F017809139FC0007E0EE03F8EE00FC0107 +814A147F717EA284A2130F5CA484011F157F5CA41902013F17075CA2F0F00F017F170E49 +6C143FB600E0011F131C94380FF83C4B01071378CA3801FFE09438003F8040407DBD43> +82 D<9239FF8003800207EBF007021F9038FC0F0091387F00FE02FCEB1F1FD903F0EB07 +BF49486DB4FC49487F4A6D5A49C8FC49157E133E137E173E49153CA57F1738A26D92C7FC +808080EB7FFEECFFE06D13FEEDFFC06D14F06D14FC010380010080143F020380DA003F7F +15031500707E163F161FA2160F121CA31607160F003C5EA35F003E151F94C7FC007E5D00 +7F153E6D5C16FC01E0495AD87DF0495AD8FCFCEB0FC03AF87F803F8027F01FFFFEC8FCD8 +E00713F839C0007FC031427BBF33>I<0007B912F0A33C0FFE000FF8003F01F0160F01C0 +4A13034848160190C7FC121EF000E048141F5E1238A212781270153F5E5AA3C81600157F +5EA515FF93C9FCA55C5DA514035DA514075DA5140F5DA3141FEC7FFC0003B7FCA33C3D76 +BC42>II87 +D<0118130C0138131C491338491370484813E039038001C0390700038000061400000E5B +48130E0018130C0038131C00301318A20070133800601330A300EFEB778039FFC07FE001 +E013F0A4397FC03FE0A2393F801FC0391E000F001E1C6CBE2D>92 +D97 +DI +IIII<177C913907F803FE91393FFE0F8F9139FC0F9C3F903901F007F89039 +07E003E0D90FC013F0011F903801F80C02801400133FD97F007FA315035B495CA3017E49 +5A5E150F6D5C6D495A90263F803EC7FCECC0FC903871FFF09038E07F8091C9FC485AA47F +A27F90B512F8EDFF806C15E016F86D8048B6FC3A07E0000FFED80F801300003FC8127F00 +3E815A00FC815AA25E163EA25E6C15FC007C4A5A6C4A5A6CEC0FC0D80FC0013FC7FC3903 +F801FCC6B512F0010F90C8FC303D7FA82D>I<147FEB3FFFA313017FA25CA513015CA513 +035CA4ED07F80107EB1FFF9139F0781FC09138F1E00F9139F38007E0ECF70002FE14F049 +5A5CA25CA24A130F131F4A14E0A4161F133F4A14C0A4163F137F91C71380A4167F5B4915 +00A300015D486C491380B5D8F87F13FCA32E3F7DBE33>I<1478EB01FE130314FFA25B14 +FE130314FCEB00F01400ACEB03F8EA01FF14F0A2EA001F130FA314E0A5131F14C0A5133F +1480A5137F1400A55B5BA4EA03FF007F13F0A2B5FC183E7DBD1A>II<147F +EB3FFFA313017FA25CA513015CA513035CA501070103B5FC02F014FEA26F13F06F1380EE +FE00010F14F84A485AED03C04B5A031FC7FC153E011F13784A5AECC3E0ECC7F0ECCFF814 +FF497F14F9ECE1FE14C04A7E4A7E4980017E133F82151F82150F01FE8049130782A20001 +81486C49B4FCB5D8F03F13F04B13E0A2303F7EBE30>I<143FEB1FFF5BA213017FA214FE +A5130114FCA5130314F8A5130714F0A5130F14E0A5131F14C0A5133F1480A5137F1400A5 +5B5BA4EA03FF007F13F8A2B5FC183F7DBE1A>I<902707F007F8EB03FCD803FFD91FFF90 +380FFF80913CE0781FC03C0FE09126E1E00FEBF0073E001FE38007E1C003F090260FE700 +EBE38002EEDAF70013F802FC14FE02D85C14F84A5CA24A5C011F020F14074A4A14F0A501 +3F021F140F4A4A14E0A5017F023F141F91C74914C0A549027F143F4992C71380A300014B +147F486C496DEBFFC0B5D8F87FD9FC3F13FEA347287DA74C>I<903907F007F8D803FFEB +1FFF9139E0781FC09138E1E00F3B001FE38007E090380FE70002EE14F014FC14D814F85C +A24A130F131F4A14E0A4161F133F4A14C0A4163F137F91C71380A4167F5B491500A30001 +5D486C491380B5D8F87F13FCA32E287DA733>II<91387F01FE +903A7FFF0FFFC09139FE3E03F09238F801F8903A01FFE000FE4B137F6D497F4990C71380 +4A15C04A141FA218E0A20103150F5C18F0A3171F010716E05CA3173F18C0130F4A147F18 +80A2EFFF004C5A011F5D16034C5A6E495AEE1FC06E495AD93FDC017EC7FC91388F01F891 +3883FFE0028090C8FC92C9FC137FA291CAFCA45BA25BA31201487EB512F8A3343A81A733 +>I<903907F01F80D803FFEB7FE09138E1E1F09138E387F839001FE707EB0FE614EE02FC +13F002D813E09138F801804AC7FCA25C131FA25CA4133F5CA5137F91C8FCA55B5BA31201 +487EB512FEA325287EA724>114 D<9138FF81C0010713E390381F807F90397C003F8049 +131F4848130F5B00031407A248481400A27FA27F6D90C7FCEBFF8014FC6C13FF6C14C015 +F06C6C7F011F7F13079038007FFE1403140100381300157EA2123C153E157E007C147CA2 +007E147815F8007F495A4A5A486C485A26F9E01FC7FC38E0FFFC38C01FE0222A7DA824> +II<01FE147F00FFEC7FFF4914FE +A20007140300031401A34914FCA4150312074914F8A41507120F4914F0A4150F121F4914 +E0A2151FA3153F4914C0157F15FFEC01DF3A0FC003BFE09138073FFF3803F01E3801FFF8 +26003FE01380282977A733>III<48B539C07FFFC0A33C +000FFE003FF8006D48EB1FE0010315800101023EC7FC6E133C01005C027F5B6F5A91383F +81C0EDC380DA1FC7C8FC15EFEC0FFE6E5A5D140381A24A7E140FEC1E7F023C7FEC383F02 +707FECE01F010180903803C00F49486C7ED90F007F491303017E80D801FE80D807FF497E +B5D8803F13F8A332277FA630>I<90B539E007FFF05E18E0902707FE000313006D48EB01 +FC705A5F01014A5A5F16036E5C0100140794C7FC160E805E805E1678ED8070023F13F05E +ED81C015C191381FC38015C793C8FC15EF15EEEC0FFCA25DA26E5AA25DA26E5A5DA24AC9 +FC5C140E141E141C5C121C003F5B5A485B495A130300FE5B4848CAFCEA701EEA783CEA3F +F0EA0FC0343A80A630>I<017FB512FEA2ECC00190397E0003FC49EB07F849EB0FF049EB +1FE049EB3FC0ED7F8000011500495B4A5A4A5A4848485A4A5AC7485A4A5A5D147F4AC7FC +495A495A49481370494813E0495A5C133F90387F8001D9FF0013C0485A48481303485A48 +48EB078049130F4848131F003F143F397F8001FFB71200A227277EA628>I +E /Fi 57 122 df<922601FFFC903801FFE0033F9026FF801F13F84AB6D8E07F13FE020F +03F9B6FC023FD9C00FB500C0138091277FFC0003D9FE0113C0902601FFE049495A494949 +494813E04990C714F049484A13E0495A19C0495A7413C0017F17804A6E6E138071913800 +7E007192C7FCAEBCFCA526007FF8C7000301C0C8FCB3B3A7007FB5D8F803B612F0A55354 +7DD34E>11 DI45 DI<157815FC14031407141F14FF130F0007B5 +FCB6FCA2147F13F0EAF800C7FCB3B3B3A6007FB712FEA52F4E76CD43>49 +DI<91380FFFC091B512FC0107ECFF80011F15E09026 +3FF8077F9026FF800113FC4848C76C7ED803F86E7E491680D807FC8048B416C080486D15 +E0A4805CA36C17C06C5B6C90C75AD801FC1680C9FC4C13005FA24C5A4B5B4B5B4B13C04B +5BDBFFFEC7FC91B512F816E016FCEEFF80DA000713E0030113F89238007FFE707E701380 +7013C018E07013F0A218F8A27013FCA218FEA2EA03E0EA0FF8487E487E487EB57EA318FC +A25E18F891C7FC6C17F0495C6C4816E001F04A13C06C484A1380D80FF84A13006CB44A5A +6CD9F0075BC690B612F06D5D011F1580010302FCC7FCD9001F1380374F7ACD43>I<177C +17FEA2160116031607160FA2161F163F167FA216FF5D5DA25D5DED1FBFED3F3F153E157C +15FCEC01F815F0EC03E01407EC0FC01580EC1F005C147E147C5C1301495A495A5C495A13 +1F49C7FC133E5B13FC485A5B485A1207485A485A90C8FC123E127E5ABA12C0A5C96C48C7 +FCAF020FB712C0A53A4F7CCE43>III<121F7F7FEB +FF8091B81280A45A1900606060A2606060485F0180C86CC7FC007EC95A4C5A007C4B5A5F +4C5A160F4C5A484B5A4C5A94C8FC16FEC812014B5A5E4B5A150F4B5AA24B5AA24B5A15FF +A24A90C9FCA25C5D1407A2140FA25D141FA2143FA4147F5DA314FFA55BAC6D5BA2EC3FC0 +6E5A395279D043>I<913807FFC0027F13FC0103B67E010F15E090261FFC0113F8903A3F +E0003FFCD97F80EB0FFE49C76C7E48488048486E1380000717C04980120F18E0177FA212 +1F7FA27F7F6E14FF02E015C014F802FE4913806C7FDBC00313009238F007FE6C02F85B92 +38FE1FF86C9138FFBFF06CEDFFE017806C4BC7FC6D806D81010F15E06D81010115FC0107 +81011F81491680EBFFE748018115C048D9007F14E04848011F14F048487F484813030300 +14F8484880161F4848020713FC1601824848157F173FA2171FA2170FA218F8A27F007F17 +F06D151FA26C6CED3FE0001F17C06D157F6C6CEDFF806C6C6C010313006C01E0EB0FFE6C +01FCEBFFFC6C6CB612F06D5D010F1580010102FCC7FCD9000F13C0364F7ACD43>I<9138 +0FFF8091B512F8010314FE010F6E7E4901037F90267FF8007F4948EB3FF048496D7E4849 +80486F7E484980824817805A91C714C05A7013E0A218F0B5FCA318F8A618FCA46C5DA37E +A25E6C7F6C5DA26C5D6C7F6C6D137B6C6D13F390387FF803011FB512E36D14C301030283 +13F89039007FFE03EC00401500A218F05EA3D801F816E0487E486C16C0487E486D491380 +A218005E5F4C5A91C7FC6C484A5A494A5A49495B6C48495BD803FC010F5B9027FF807FFE +C7FC6C90B55A6C6C14F06D14C0010F49C8FC010013F0364F7ACD43>II<171F4D7E4D7EA24D7EA34C7FA24C7FA34C +7FA34C7FA24C7FA34C8083047F80167E8304FE804C7E03018116F8830303814C7E030781 +16E083030F814C7E031F81168083033F8293C77E4B82157E8403FE824B800201835D8402 +03834B800207835D844AB87EA24A83A3DA3F80C88092C97E4A84A2027E8202FE844A8201 +0185A24A820103854A82010785A24A82010F855C011F717FEBFFFCB600F8020FB712E0A5 +5B547BD366>65 DI<932601 +FFFCEC01C0047FD9FFC013030307B600F81307033F03FE131F92B8EA803F0203DAE003EB +C07F020F01FCC7383FF0FF023F01E0EC0FF94A01800203B5FC494848C9FC4901F8824949 +824949824949824949824990CA7E494883A2484983485B1B7F485B481A3FA24849181FA3 +485B1B0FA25AA298C7FC5CA2B5FCAE7EA280A2F307C07EA36C7FA21B0F6C6D1980A26C1A +1F6C7F1C006C6D606C6D187EA26D6C606D6D4C5A6D6D16036D6D4C5A6D6D4C5A6D01FC4C +5A6D6DEE7F806D6C6C6C4BC7FC6E01E0EC07FE020F01FEEC1FF80203903AFFE001FFF002 +0091B612C0033F93C8FC030715FCDB007F14E0040101FCC9FC525479D261>IIII<932601FFFCEC01C0047FD9FFC013030307B600F81307033F03FE131F92B8EA +803F0203DAE003EBC07F020F01FCC7383FF0FF023F01E0EC0FF94A01800203B5FC494848 +C9FC4901F8824949824949824949824949824990CA7E494883A2484983485B1B7F485B48 +1A3FA24849181FA3485B1B0FA25AA298C8FC5CA2B5FCAE6C057FB712E0A280A36C94C700 +3FEBC000A36C7FA36C7FA27E6C7FA26C7F6C7FA26D7E6D7F6D7F6D6D5E6D7F6D01FC93B5 +FC6D13FF6D6C6D5C6E01F0EC07FB020F01FEEC1FF10203903AFFF001FFE0020091B6EAC0 +7F033FEE001F030703FC1307DB007F02E01301040149CAFC5B5479D26A>III75 D +III<93380FFFC00303B6FC031F15E092B712FC02 +03D9FC0013FF020F01C0010F13C0023F90C7000313F0DA7FFC02007F494848ED7FFE4901 +E0ED1FFF49496F7F49496F7F4990C96C7F49854948707F4948707FA24849717E48864A83 +481B804A83481BC0A2481BE04A83A2481BF0A348497113F8A5B51AFCAF6C1BF86E5FA46C +1BF0A26E5F6C1BE0A36C6D4D13C0A26C6D4D1380A26C1B006C6D4D5A6E5E6C626D6C4C5B +6D6D4B5B6D6D4B5B6D6D4B5B6D6D4B5B6D6D4B90C7FC6D6D4B5A6D01FF02035B023F01E0 +011F13F0020F01FC90B512C0020390B7C8FC020016FC031F15E0030392C9FCDB001F13E0 +565479D265>II82 +D<91260FFF80130791B500F85B010702FF5B011FEDC03F49EDF07F9026FFFC006D5A4801 +E0EB0FFD4801800101B5FC4848C87E48488149150F001F824981123F4981007F82A28412 +FF84A27FA26D82A27F7F6D93C7FC14C06C13F014FF15F86CECFF8016FC6CEDFFC017F06C +16FC6C16FF6C17C06C836C836D826D82010F821303010082021F16801400030F15C0ED00 +7F040714E01600173F050F13F08383A200788200F882A3187FA27EA219E07EA26CEFFFC0 +A27F6D4B13806D17006D5D01FC4B5A01FF4B5A02C04A5A02F8EC7FF0903B1FFFC003FFE0 +486C90B65AD8FC0393C7FC48C66C14FC48010F14F048D9007F90C8FC3C5479D24B>I<00 +3FBC1280A59126C0003F9038C0007F49C71607D87FF8060113C001E08449197F49193F90 +C8171FA2007E1A0FA3007C1A07A500FC1BE0481A03A6C994C7FCB3B3AC91B912F0A55351 +7BD05E>II87 D89 D97 DI<913801FFF8021FEBFF8091B612F0010315FC010F90 +38C00FFE903A1FFE0001FFD97FFC491380D9FFF05B4817C048495B5C5A485BA2486F1380 +91C7FC486F1300705A4892C8FC5BA312FFAD127F7FA27EA2EF03E06C7F17076C6D15C07E +6E140F6CEE1F806C6DEC3F006C6D147ED97FFE5C6D6CEB03F8010F9038E01FF0010390B5 +5A01001580023F49C7FC020113E033387CB63C>I<4DB47E0407B5FCA5EE001F1707B3A4 +913801FFE0021F13FC91B6FC010315C7010F9038E03FE74990380007F7D97FFC0101B5FC +49487F4849143F484980485B83485B5A91C8FC5AA3485AA412FFAC127FA36C7EA37EA26C +7F5F6C6D5C7E6C6D5C6C6D49B5FC6D6C4914E0D93FFED90FEFEBFF80903A0FFFC07FCF6D +90B5128F0101ECFE0FD9003F13F8020301C049C7FC41547CD24B>I<913803FFC0023F13 +FC49B6FC010715C04901817F903A3FFC007FF849486D7E49486D7E4849130F48496D7E48 +178048497F18C0488191C7FC4817E0A248815B18F0A212FFA490B8FCA318E049CAFCA612 +7FA27F7EA218E06CEE01F06E14037E6C6DEC07E0A26C6DEC0FC06C6D141F6C6DEC3F806D +6CECFF00D91FFEEB03FE903A0FFFC03FF8010390B55A010015C0021F49C7FC020113F034 +387CB63D>IIII<137F497E000313E0487FA2487FA76C5BA26C5BC613806DC7FC90C8FCADEB +3FF0B5FCA512017EB3B3A6B612E0A51B547BD325>I108 DII< +913801FFE0021F13FE91B612C0010315F0010F9038807FFC903A1FFC000FFED97FF86D6C +7E49486D7F48496D7F48496D7F4A147F48834890C86C7EA24883A248486F7EA3007F1880 +A400FF18C0AC007F1880A3003F18006D5DA26C5FA26C5F6E147F6C5F6C6D4A5A6C6D495B +6C6D495B6D6C495BD93FFE011F90C7FC903A0FFF807FFC6D90B55A010015C0023F91C8FC +020113E03A387CB643>I<903A3FF001FFE0B5010F13FE033FEBFFC092B612F002F30101 +7F913AF7F8007FFE0003D9FFE0EB1FFFC602806D7F92C76C7F4A824A6E7F4A6E7FA2717F +A285187F85A4721380AC1A0060A36118FFA2615F616E4A5BA26E4A5B6E4A5B6F495B6F49 +90C7FC03F0EBFFFC9126FBFE075B02F8B612E06F1480031F01FCC8FC030313C092CBFCB1 +B612F8A5414D7BB54B>I<90397FE003FEB590380FFF80033F13E04B13F09238FE1FF891 +39E1F83FFC0003D9E3E013FEC6ECC07FECE78014EF150014EE02FEEB3FFC5CEE1FF8EE0F +F04A90C7FCA55CB3AAB612FCA52F367CB537>114 D<903903FFF00F013FEBFE1F90B7FC +120348EB003FD80FF81307D81FE0130148487F4980127F90C87EA24881A27FA27F01F091 +C7FC13FCEBFFC06C13FF15F86C14FF16C06C15F06C816C816C81C681013F1580010F15C0 +1300020714E0EC003F030713F015010078EC007F00F8153F161F7E160FA27E17E07E6D14 +1F17C07F6DEC3F8001F8EC7F0001FEEB01FE9039FFC00FFC6DB55AD8FC1F14E0D8F80714 +8048C601F8C7FC2C387CB635>I<143EA6147EA414FEA21301A313031307A2130F131F13 +3F13FF5A000F90B6FCB8FCA426003FFEC8FCB3A9EE07C0AB011FEC0F8080A26DEC1F0015 +806DEBC03E6DEBF0FC6DEBFFF86D6C5B021F5B020313802A4D7ECB34>IIII<007FB500F090387FFFFEA5C66C48C7000F90C7 +FC6D6CEC07F86D6D5C6D6D495A6D4B5A6F495A6D6D91C8FC6D6D137E6D6D5B91387FFE01 +4C5A6E6C485A6EEB8FE06EEBCFC06EEBFF806E91C9FCA26E5B6E5B6F7E6F7EA26F7F834B +7F4B7F92B5FCDA01FD7F03F87F4A486C7E4A486C7E020F7FDA1FC0804A486C7F4A486C7F +02FE6D7F4A6D7F495A49486D7F01076F7E49486E7E49486E7FEBFFF0B500FE49B612C0A5 +42357EB447>II E /Fj 47 122 df +45 D<16F04B7E1507151F153FEC01FF1407147F010FB5FCB7FCA41487EBF007C7FCB3B3 +B3B3007FB91280A6395E74DD51>49 D<913801FFF8021FEBFFC091B612F8010315FF010F +16C0013F8290267FFC0114F89027FFE0003F7F4890C7000F7F48486E7FD807F86E148048 +486E14C048486E14E048486F13F001FC17F8486C816D17FC6E80B56C16FE8380A219FFA2 +83A36C5BA26C5B6C90C8FCD807FC5DEA01F0CA14FEA34D13FCA219F85F19F04D13E0A294 +B512C019804C14004C5B604C5B4C5B604C13804C90C7FC4C5A4C5A4B13F05F4B13804B90 +C8FC4B5AED1FF84B5A4B5A4B48143F4A5B4A48C8FC4A5A4A48157E4A5A4A5AEC7F8092C9 +FC02FE16FE495A495A4948ED01FCD90FC0150749B8FC5B5B90B9FC5A4818F85A5A5A5A5A +BAFCA219F0A4405E78DD51>I<92B5FC020F14F8023F14FF49B712C04916F0010FD9C01F +13FC90271FFC00077FD93FE001017F49486D8049C86C7F484883486C6F7F14C0486D826E +806E82487FA4805CA36C5E4A5E6C5B6C5B6C495E011FC85A90C95CA294B55A614C91C7FC +604C5B4C5B4C5B4C5B047F138092260FFFFEC8FC020FB512F817E094C9FC17F817FF91C7 +003F13E0040713F8040113FE707F717F7113E085717FA2717F85A285831A80A31AC0EA03 +FCEA0FFF487F487F487FA2B57EA31A80A34D14005C7E4A5E5F6C495E49C8485BD81FF85F +000F5ED807FE92B55A6C6C6C4914806C01F0010791C7FC6C9026FF803F5B6D90B65A011F +16F0010716C001014BC8FCD9001F14F0020149C9FC426079DD51>II<01C0EE01C0D801F8160F01FF16 +7F02F0EC07FFDAFF8090B5FC92B7128019006060606060606095C7FC17FC5F17E0178004 +FCC8FC16E09026FC3FFCC9FC91CBFCADED3FFE0203B512F0020F14FE023F6E7E91B712E0 +01FDD9E00F7F9027FFFE00037F02F801007F02E06EB4FC02806E138091C8FC496F13C049 +17E07113F0EA00F090C914F8A219FC83A219FEA419FFA3EA03F0EA0FFC487E487E487FA2 +B57EA319FEA35C4D13FC6C90C8FC5B4917F8EA3FF001804B13F06D17E0001F5E6C6C17C0 +6D4B1380D807FC92B512006C6C4A5B6C6C6C01075B6C01E0011F5BD97FFE90B55A6DB712 +C0010F93C7FC6D15FC010115F0D9003F1480020301F0C8FC406078DD51>III<9238 +3FFF800203B512FC021FECFF80027F15E049B712F849D9F0077F010F90C76C7ED91FFCEC +1FFFD93FF06E7F494802037F494882717F484980854890C9127FA24884183FA25A80A380 +806E157F6E5E14FE6E7E6F4A5A6C14F003FC495B03FF495B6C1580DCE0075B6CDBF80F90 +C7FC9338FE1FFE6C9238FF7FF84D5A6D16C06D5E6D4BC8FC6D6F7E6D16E00101826D16FC +023F814A8149B87E010783498390263FFE3F8190267FFC0F819026FFF003814849C6FC48 +496D804849131F4890C7000780160148486E1580003F163F49150F007F7014C049150171 +7E8400FF835B8484A384A21A80A27F007F1900607F003F606D160F001F606D4C5A6C6D15 +3F6C6D4B5A6C01F04B5A6C01FC02035B6C01FF021F5B6D9027F001FFFEC7FC6D90B65A01 +0F16F001035E010093C8FC020F14F8DA007F90C9FC426079DD51>I65 DI<4DB5ED03 +C0057F02F014070407B600FE140F047FDBFFC0131F4BB800F0133F030F05FC137F033F91 +27F8007FFE13FF92B6C73807FF814A02F0020113C3020702C09138007FE74A91C9001FB5 +FC023F01FC16074A01F08291B54882490280824991CB7E49498449498449498449865D49 +498490B5FC484A84A2484A84A24891CD127FA25A4A1A3F5AA348491A1FA44899C7FCA25C +A3B5FCB07EA380A27EA2F50FC0A26C7FA37E6E1A1F6C1D80A26C801D3F6C6E1A00A26C6E +616D1BFE6D7F6F4E5A7F6D6D4E5A6D6D4E5A6D6D4E5A6D6E171F6D02E04D5A6E6DEFFF80 +6E01FC4C90C7FC020F01FFEE07FE6E02C0ED1FF8020102F8ED7FF06E02FF913803FFE003 +3F02F8013F1380030F91B648C8FC030117F86F6C16E004071680DC007F02F8C9FC050191 +CAFC626677E375>III<4D +B5ED03C0057F02F014070407B600FE140F047FDBFFC0131F4BB800F0133F030F05FC137F +033F9127F8007FFE13FF92B6C73807FF814A02F0020113C3020702C09138007FE74A91C9 +001FB5FC023F01FC16074A01F08291B54882490280824991CB7E49498449498449498449 +865D49498490B5FC484A84A2484A84A24891CD127FA25A4A1A3F5AA348491A1FA44899C8 +FCA25CA3B5FCB07E071FB812F880A37EA296C70001ECC000A26C7FA37E807EA26C80A26C +80A26C807F6D7F816D7F7F6D7F6D6D5F6D14C06D6E5E6E7F6E01FC5E020F01FF5E6E02C0 +ED7FEF020102F8EDFFC76E02FF02071383033F02FC013F1301030F91B638FC007F03014D +131F6F6C04E01307040704801301DC007F02F8CAFC050191CBFC6D6677E37F>71 +DI +I75 DI78 D<94381FFFE00407B67E043F15F04BB712 +FE030FEEFFC0033FD9FC0014F092B500C0010F13FC020349C7000113FF4A01F86E6C7F02 +1F496F13E04A01C0030F7F4A496F7F91B5C96C7F0103497013FF494970804B834949717F +49874949717F49874B8390B586484A717FA24891CB6C7FA2481D804A84481DC0A3484972 +14E0A3481DF0A34A85481DF8A5B51CFCB06C1DF8A36E96B5FCA36C1DF0A46C6D4E14E0A3 +6C1DC06E606C1D80A26C6E4D1400A26C6E4D5BA26C6E4D5BA26D6D4D5B6D636D6D4D5B6F +94B5FC6D636D6D4C5C6D6D4C91C7FC6D6E4B5B6D02E0031F5B023F6D4B13F06E01FC92B5 +5A6E01FF02035C020302C0010F91C8FC020002FC90B512FC033F90B712F0030F17C00303 +94C9FCDB007F15F804071580DC001F01E0CAFC666677E379>II82 DI<001FBEFCA64849C79126E0000F148002E0180091C8171F498601F81A0349864986 +A2491B7FA2491B3F007F1DC090C9181FA4007E1C0FA600FE1DE0481C07A5CA95C7FCB3B3 +B3A3021FBAFCA663617AE070>II<913803FFFE027FEBFFF00103B612FE010F6F7E4916E090273FFE001F7F +D97FE001077FD9FFF801017F486D6D7F717E486D6E7F85717FA2717FA36C496E7FA26C5B +6D5AEB1FC090C9FCA74BB6FC157F0207B7FC147F49B61207010F14C0013FEBFE004913F0 +48B512C04891C7FC485B4813F85A5C485B5A5CA2B55AA45FA25F806C5E806C047D7F6EEB +01F96C6DD903F1EBFF806C01FED90FE114FF6C9027FFC07FC01580000191B5487E6C6C4B +7E011F02FC130F010302F001011400D9001F90CBFC49437CC14E>97 +D<903807FF80B6FCA6C6FC7F7FB3A8EFFFF8040FEBFF80047F14F00381B612FC038715FF +038F010014C0DBBFF0011F7FDBFFC001077F93C76C7F4B02007F03F8824B6F7E4B6F1380 +4B17C0851BE0A27313F0A21BF8A37313FCA41BFEAE1BFCA44F13F8A31BF0A24F13E0A24F +13C06F17804F1300816F4B5A6F4A5B4AB402075B4A6C6C495B9126F83FE0013F13C09127 +F00FFC03B55A4A6CB648C7FCDAC00115F84A6C15E091C7001F91C8FC90C8000313E04F65 +7BE35A>I<92380FFFF04AB67E020F15F0023F15FC91B77E01039039FE001FFF4901F801 +0113804901E0010713C04901804913E0017F90C7FC49484A13F0A2485B485B5A5C5A7113 +E0485B7113C048701380943800FE0095C7FC485BA4B5FCAE7EA280A27EA2806C18FCA26C +6D150119F87E6C6D15036EED07F06C18E06C6D150F6D6DEC1FC06D01E0EC7F806D6DECFF +00010701FCEB03FE6D9039FFC03FFC010091B512F0023F5D020F1580020102FCC7FCDA00 +0F13C03E437BC148>II<92380FFFC04AB512FC020FECFF80023F15E091B712F80103D9FE03 +7F499039F0007FFF011F01C0011F7F49496D7F4990C76C7F49486E7F48498048844A8048 +84485B727E5A5C48717EA35A5C721380A2B5FCA391B9FCA41A0002C0CBFCA67EA380A27E +A27E6E160FF11F806C183F6C7FF17F006C7F6C6D16FE6C17016D6C4B5A6D6D4A5A6D01E0 +4A5A6D6DEC3FE0010301FC49B45A6D9026FFC01F90C7FC6D6C90B55A021F15F8020715E0 +020092C8FC030713F041437CC14A>III<903807FF80B6FCA6C6FC +7F7FB3A8EF1FFF94B512F0040714FC041F14FF4C8193267FE07F7F922781FE001F7FDB83 +F86D7FDB87F07FDB8FC0814C7F039FC78015BE03BC8003FC825DA25DA25DA45DB3B2B7D8 +F007B71280A651647BE35A>II<903807FF80B6FCA6C6FC7F7FB3B3B3B3ADB712E0A623647BE32C>108 +D<902607FF80D91FFFEEFFF8B691B500F00207EBFF80040702FC023F14E0041F02FF91B6 +12F84C6F488193267FE07F6D4801037F922781FE001F9027E00FF0007FC6DA83F86D9026 +F01FC06D7F6DD987F06D4A487F6DD98FC0DBF87EC7804C6D027C80039FC76E488203BEEE +FDF003BC6E4A8003FC04FF834B5FA24B5FA24B94C8FCA44B5EB3B2B7D8F007B7D8803FB6 +12FCA67E417BC087>I<902607FF80EB1FFFB691B512F0040714FC041F14FF4C8193267F +E07F7F922781FE001F7FC6DA83F86D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC +8003FC825DA25DA25DA45DB3B2B7D8F007B71280A651417BC05A>I<923807FFE092B6FC +020715E0021F15F8027F15FE494848C66C6C7E010701F0010F13E04901C001037F49496D +7F4990C87F49486F7E49486F7E48496F13804819C04A814819E048496F13F0A24819F8A3 +48496F13FCA34819FEA4B518FFAD6C19FEA46C6D4B13FCA36C19F8A26C6D4B13F0A26C19 +E06C6D4B13C0A26C6D4B13806C6D4B13006D6C4B5A6D6D495B6D6D495B010701F0010F13 +E06D01FE017F5B010090B7C7FC023F15FC020715E0020092C8FC030713E048437CC151> +I<902607FF80EBFFF8B6010FEBFF80047F14F00381B612FC038715FF038F010114C09227 +BFF0003F7FC6DAFFC0010F7F6D91C76C7F6D496E7F03F86E7F4B6E7F4B17804B6F13C0A2 +7313E0A27313F0A21BF885A21BFCA3851BFEAE4F13FCA41BF861A21BF0611BE0611BC06F +92B512801B006F5C6F4A5B6F4A5B03FF4A5B70495B04E0017F13C09226CFFC03B55A03C7 +B648C7FC03C115F803C015E0041F91C8FC040313E093CBFCB3A3B712F0A64F5D7BC05A> +I114 D<913A3FFF8007800107B5EAF81F011FEC +FE7F017F91B5FC48B8FC48EBE0014890C7121FD80FFC1407D81FF0801600485A007F167F +49153FA212FF171FA27F7F7F6D92C7FC13FF14E014FF6C14F8EDFFC06C15FC16FF6C16C0 +6C16F06C826C826C826C82013F1680010F16C01303D9007F15E0020315F0EC001F150004 +1F13F81607007C150100FC81177F6C163FA2171F7EA26D16F0A27F173F6D16E06D157F6D +16C001FEEDFF806D0203130002C0EB0FFE02FCEB7FFC01DFB65A010F5DD8FE0315C026F8 +007F49C7FC48010F13E035437BC140>II<902607FFC0ED3FFEB60207B5FCA6C6EE00076D826D82B3B3 +A260A360A2607F60183E6D6D147E4E7F6D6D4948806D6DD907F0ECFF806D01FFEB3FE06D +91B55A6E1500021F5C020314F8DA003F018002F0C7FC51427BC05A>III121 D E /Fk 83 126 df<00101304007C131F00FEEB +3F80A26C137FA248133FB2007E1400007C7F003C131E00101304191C75B830>34 +D<903907C007C0A2496C487EA8011F131FA202C05BA3007FB7FCA2B81280A36C16006C5D +3A007F807F80A2020090C7FCA9495BA2003F90B512FE4881B81280A36C1600A22701FC01 +FCC7FCA300031303A201F85BA76C486C5AA229387DB730>I<1438147C14FCA4EB03FF01 +1F13E090B512FC4880000780481580261FFEFD13C09039F0FC3FE0D83FC0131FD87F80EB +0FF001001307007E15F800FE14035A1507A36CEC03F0A2007F91C7FC138013C0EA3FF0EA +1FFE13FF6C13FF6C14E0000114F86C6C7F011F7F01037F0100148002FD13C09138FC7FE0 +151FED0FF015070018EC03F8127E1501B4FCA35AA26CEC03F07E01801307ED0FE0D83FC0 +131F01F0EB7FC0D81FFEB512806CB612006C5C6C5CC614F0013F13C0D907FEC7FCEB00FC +A5147C143825477BBE30>IIII<141E147F14FF5BEB03FEEB07FCEB0FF0EB1FE0EB3FC0EB7F80EBFF +00485A5B12035B485A120F5BA2485AA2123F5BA2127F90C7FCA412FEAD127FA47F123FA2 +7F121FA26C7EA27F12076C7E7F12017F6C7EEB7F80EB3FC0EB1FE0EB0FF0EB07FCEB03FE +EB01FF7F147F141E184771BE30>I<127812FE7E7F6C7E6C7EEA0FF06C7E6C7E6C7E6C7E +EB7F80133F14C0131FEB0FE014F01307A2EB03F8A214FC1301A214FE1300A4147FAD14FE +A4130114FCA2130314F8A2EB07F0A2130F14E0EB1FC0133F1480137FEBFF00485A485A48 +5A485AEA3FE0485A485A90C7FC5A1278184778BE30>I<14E0497E497EA60038EC038000 +7EEC0FC0D8FF83EB3FE001C3137F9038F3F9FF267FFBFB13C06CB61280000FECFE000003 +14F86C5C6C6C13C0011F90C7FC017F13C048B512F04880000F14FE003FECFF80267FFBFB +13C026FFF3F913E09038C3F87F0183133FD87E03EB0FC00038EC0380000091C7FCA66D5A +6D5A23277AAE30>I<143EA2147FAF007FB7FCA2B81280A36C1600A2C76CC8FCAF143EA2 +29297DAF30>II<007FB612 +F0A2B712F8A36C15F0A225077B9E30>I<120FEA3FC0EA7FE0A2EAFFF0A4EA7FE0A2EA3F +C0EA0F000C0C6E8B30>I<16F01501ED03F8A21507A2ED0FF0A2ED1FE0A2ED3FC0A2ED7F +80A2EDFF00A24A5AA25D1403A24A5AA24A5AA24A5AA24A5AA24A5AA24AC7FCA2495AA25C +1303A2495AA2495AA2495AA2495AA2495AA249C8FCA2485AA25B1203A2485AA2485AA248 +5AA2485AA2485AA248C9FCA25AA2127CA225477BBE30>I<14FE903807FFC0497F013F13 +F8497F90B57E48EB83FF4848C6138049137F4848EB3FC04848EB1FE049130F001F15F049 +1307A24848EB03F8A290C712014815FCA400FEEC00FEAD6C14016C15FCA36D1303003F15 +F8A26D1307001F15F0A26D130F6C6CEB1FE0A26C6CEB3FC06C6CEB7F806D13FF2601FF83 +13006CEBFFFE6D5B6D5B010F13E06D5BD900FEC7FC273A7CB830>IIIII<000FB612804815C05AA316800180C8FCAEEB83FF019F13 +C090B512F015FC8181D9FE0313809039F0007FC049133F0180EB1FE06CC7120F000E15F0 +C81207A216F81503A31218127EA2B4FC150716F048140F6C15E06C141F6DEB3FC06D137F +3A3FE001FF80261FFC0F13006CB55A6C5C6C5C6C14E06C6C1380D90FFCC7FC25397BB730 +>II<127CB712FC16FEA416FC48C7EA0FF816F0ED1FE0007CEC3FC0C8EA7F80EDFF +00A24A5A4A5A5D14075D140F5D4A5AA24A5AA24AC7FCA25C5C13015CA213035CA213075C +A4495AA6131F5CA96D5A6DC8FC273A7CB830>I<49B4FC011F13F0017F13FC90B57E0003 +ECFF804815C048010113E03A1FF8003FF049131FD83FC0EB07F8A24848EB03FC90C71201 +A56D1303003F15F86D13076C6CEB0FF06C6CEB1FE0D807FCEB7FC03A03FF83FF806C90B5 +12006C6C13FC011F13F0497F90B512FE48802607FE0013C0D80FF8EB3FE0D81FE0EB0FF0 +4848EB07F8491303007F15FC90C712014815FE481400A66C14016C15FC6D1303003F15F8 +6D1307D81FF0EB1FF06D133F3A0FFF01FFE06C90B512C06C1580C6ECFE006D5B011F13F0 +010190C7FC273A7CB830>I<49B4FC010F13E0013F13F890B57E4880488048010113803A +0FFC007FC0D81FF0EB3FE04848131F49EB0FF048481307A290C7EA03F85A4815FC1501A4 +16FEA37E7E6D130315076C7E6C6C130F6D133FD80FFC13FF6CB6FC7E6C14FE6C14F9013F +EBE1FC010F138190380060011400ED03F8A2150716F0150F000F15E0486C131F486CEB3F +C0157FEDFF804A1300EC07FE391FF01FFC90B55A6C5C6C5C6C1480C649C7FCEB3FF0273A +7CB830>I59 D<16F01503ED07F8151F157FEDFFF01403 +4A13C0021F138091383FFE00ECFFF8495B010713C0495BD93FFEC7FC495A3801FFF0485B +000F13804890C8FCEA7FFC5BEAFFE05B7FEA7FF87FEA1FFF6C7F000313E06C7F38007FFC +6D7E90380FFF806D7F010113F06D7FEC3FFE91381FFF80020713C06E13F01400ED7FF815 +1F1507ED03F01500252F7BB230>I<007FB7FCA2B81280A36C16006C5DCBFCA7003FB612 +FE4881B81280A36C1600A229157DA530>I<1278127EB4FC13C07FEA7FF813FEEA1FFF6C +13C000037F6C13F86C6C7EEB1FFF6D7F010313E06D7F9038007FFC6E7E91380FFF806E13 +C0020113F080ED3FF8151F153FEDFFF05C020713C04A138091383FFE004A5A903801FFF0 +495B010F13804990C7FCEB7FFC48485A4813E0000F5B4890C8FCEA7FFE13F8EAFFE05B90 +C9FC127E1278252F7BB230>I64 D<147F4A7EA2497FA4497F14F7A401077F14E3A3010F7FA314C1A201 +1F7FA490383F80FEA590387F007FA4498049133F90B6FCA34881A39038FC001F00038149 +130FA4000781491307A2D87FFFEB7FFFB56CB51280A46C496C130029397DB830>I<007F +B512F0B612FE6F7E82826C813A03F8001FF815076F7E1501A26F7EA615015EA24B5A1507 +ED1FF0ED7FE090B65A5E4BC7FC6F7E16E0829039F8000FF8ED03FC6F7E1500167FA3EE3F +80A6167F1700A25E4B5A1503ED1FFC007FB6FCB75A5E16C05E6C02FCC7FC29387EB730> +I<91387F803C903903FFF03E49EBFC7E011F13FE49EBFFFE5B9038FFE07F48EB801F3903 +FE000F484813075B48481303A2484813015B123F491300A2127F90C8FC167C16005A5AAC +7E7EA2167C6D14FE123FA27F121F6D13016C6C14FCA26C6CEB03F86D13076C6CEB0FF039 +01FF801F6C9038E07FE06DB512C06D14806D1400010713FC6D13F09038007FC0273A7CB8 +30>I<003FB512E04814FCB67E6F7E6C816C813A03F8007FF0ED1FF8150F6F7E6F7E1501 +6F7EA2EE7F80A2163F17C0161FA4EE0FE0AC161F17C0A3163F1780A2167F17005E4B5A15 +034B5A150F4B5AED7FF0003FB65A485DB75A93C7FC6C14FC6C14E02B387FB730>I<007F +B7FCB81280A47ED803F8C7123FA8EE1F0093C7FCA4157C15FEA490B5FCA6EBF800A4157C +92C8FCA5EE07C0EE0FE0A9007FB7FCB8FCA46C16C02B387EB730>I<003FB712804816C0 +B8FCA27E7ED801FCC7121FA8EE0F8093C7FCA5153E157FA490B6FCA69038FC007FA4153E +92C8FCAE383FFFF8487FB5FCA27E6C5B2A387EB730>I<02FF13F00103EBC0F8010F13F1 +013F13FD4913FF90B6FC4813C1EC007F4848133F4848131F49130F485A491307121F5B12 +3F491303A2127F90C7FC6F5A92C8FC5A5AA892B5FC4A14805CA26C7F6C6D1400ED03F8A2 +7F003F1407A27F121F6D130F120F7F6C6C131FA2D803FE133F6C6C137FECC1FF6C90B5FC +7F6D13FB010F13F30103EBC1F0010090C8FC293A7DB830>I<3B3FFF800FFFE0486D4813 +F0B56C4813F8A26C496C13F06C496C13E0D803F8C7EAFE00B290B6FCA601F8C7FCB3A23B +3FFF800FFFE0486D4813F0B56C4813F8A26C496C13F06C496C13E02D387FB730>I<007F +B6FCB71280A46C1500260007F0C7FCB3B3A8007FB6FCB71280A46C1500213879B730>I< +49B512F04914F85BA27F6D14F090C7EAFE00B3B3123C127EB4FCA24A5A1403EB8007397F +F01FF86CB55A5D6C5C00075C000149C7FC38003FF025397AB730>II<383FFFF8 +487FB57EA26C5B6C5BD801FCC9FCB3B0EE0F80EE1FC0A9003FB7FC5AB8FCA27E6C16802A +387EB730>III<90383FFFE048B512FC000714FF4815804815C04815E0EBF80001E013 +3FD87F80EB0FF0A290C71207A44815F8481403B3A96C1407A26C15F0A36D130FA26D131F +6C6CEB3FE001F813FF90B6FC6C15C06C15806C1500000114FCD8003F13E0253A7BB830> +I<007FB512F0B612FE6F7E16E0826C813903F8003FED0FFCED03FE15016F7EA282178016 +3FA6167F17005EA24B5A1503ED0FFCED3FF890B6FC5E5E16804BC7FC15F001F8C9FCB038 +7FFFC0B57EA46C5B29387EB730>I<003FB57E4814F0B612FC15FF6C816C812603F8017F +9138003FF0151F6F7E15071503821501A515035E1507150F4B5A153F4AB45A90B65A5E93 +C7FC5D8182D9F8007FED3FE0151F150F821507A817F8EEF1FCA53A3FFF8003FB4801C0EB +FFF8B56C7E17F06C496C13E06C49EB7FC0C9EA1F002E397FB730>82 +D<90390FF803C0D97FFF13E048B512C74814F74814FF5A381FF80F383FE001497E484813 +7F90C7123F5A48141FA2150FA37EED07C06C91C7FC7F7FEA3FF0EA1FFEEBFFF06C13FF6C +14E0000114F86C80011F13FF01031480D9003F13C014019138007FE0151FED0FF0A2ED07 +F8A2007C140312FEA56C140716F07F6DEB0FE06D131F01F8EB3FC001FF13FF91B5128016 +0000FD5CD8FC7F13F8D8F81F5BD878011380253A7BB830>I<003FB712C04816E0B8FCA4 +3AFE003F800FA8007CED07C0C791C7FCB3B1011FB5FC4980A46D91C7FC2B387EB730>I< +3B7FFFC007FFFCB56C4813FEA46C496C13FCD803F8C7EA3F80B3B16D147F00011600A36C +6C14FE6D13016D5CEC800390393FE00FF890391FF83FF06DB55A6D5C6D5C6D91C7FC9038 +007FFCEC1FF02F3980B730>III89 D<001FB612FC4815FE5AA490C7EA03FCED07F816F0150FED1FE016C015 +3FED7F80003E1500C85A4A5A5D14034A5A5D140F4A5A5D143F4A5A92C7FC5C495A5C1303 +495A5C130F495A5C133F495A91C8FC5B4848147C4914FE1203485A5B120F485A5B123F48 +5A90B6FCB7FCA46C15FC27387CB730>I<127CA212FEA27EA26C7EA26C7EA26C7EA26C7E +A26C7EA26C7EA212017FA26C7EA26D7EA26D7EA26D7EA26D7EA26D7EA26D7EA2130180A2 +6D7EA26E7EA26E7EA26E7EA26E7EA26E7EA26E7EA2140181A26E7EA2ED7F80A2ED3FC0A2 +ED1FE0A2ED0FF0A2ED07F8A21503A2ED01F0150025477BBE30>92 +D<007FB612F0A2B712F8A36C15F0A225077B7D30>95 D<1338137CEA01FE12031207EA0F +FC13F0EA1FE013C0EA3F8013005A127EA212FE5AA5EAFFC013E013F0127FA2123FA2EA1F +E0EA07C00F1D70BE30>IIII<913801FFE04A7F5CA28080EC0007AAEB03FE90381FFF +874913E790B6FC5A5A481303380FFC00D81FF0133F49131F485A150F4848130790C7FCA2 +5AA25AA87E6C140FA27F003F141F6D133F6C7E6D137F390FF801FF2607FE07EBFFC06CB7 +12E06C16F06C14F76D01C713E0011F010313C0D907FCC8FC2C397DB730>I<49B4FC0107 +13E0011F13F8017F7F90B57E488048018113803A07FC007FC04848133FD81FE0EB1FE015 +0F484814F0491307127F90C7FCED03F85A5AB7FCA516F048C9FC7E7EA27F003FEC01F06D +EB03F86C7E6C7E6D1307D807FEEB1FF03A03FFC07FE06C90B5FC6C15C0013F14806DEBFE +00010713F8010013C0252A7CA830>IIII<14E0EB03F8A2497EA36D5AA2EB00 +E091C8FCA9381FFFF8487F5AA27E7EEA0001B3A9003FB612C04815E0B7FCA27E6C15C023 +397AB830>III<387FFFF8B57EA47E +EA0001B3B3A8007FB612F0B712F8A46C15F025387BB730>I<02FC137E3B7FC3FF01FF80 +D8FFEF01877F90B500CF7F15DF92B57E6C010F13872607FE07EB03F801FC13FE9039F803 +FC01A201F013F8A301E013F0B3A23C7FFE0FFF07FF80B548018F13C0A46C486C01071380 +322881A730>II<49B4FC010F13E0013F13F8497F90 +B57E0003ECFF8014013A07FC007FC04848EB3FE0D81FE0EB0FF0A24848EB07F849130300 +7F15FC90C71201A300FEEC00FEA86C14016C15FCA26D1303003F15F86D13076D130F6C6C +EB1FF06C6CEB3FE06D137F3A07FF01FFC06C90B512806C15006C6C13FC6D5B010F13E001 +0190C7FC272A7CA830>II< +ED07F83A3FFF803FFF486DB51280B512C302CF14C06C13DF6C9038FFFC3FD8001F13E092 +38801F809238000F004A90C7FC5C5C5CA25CA45CAF003FB512FC4880B7FCA26C5C6C5C2A +287EA730>114 D<90381FFC1E48B5129F000714FF5A5A5A387FF007EB800100FEC7FC48 +80A46C143E007F91C7FC13E06CB4FC6C13FC6CEBFF806C14E0000114F86C6C7F01037F90 +38000FFF02001380007C147F00FEEC1FC0A2150F7EA27F151F6DEB3F806D137F9039FC03 +FF0090B6FC5D5D00FC14F0D8F83F13C026780FFEC7FC222A79A830>III<3B3FFFC07FFF80486DB512C0B515E0A26C16C06C496C13803B01F80003F000A26D +130700005DA26D130F017E5CA2017F131F6D5CA2EC803F011F91C7FCA26E5A010F137EA2 +ECE0FE01075BA214F101035BA3903801FBF0A314FF6D5BA36E5A6E5A2B277EA630>I<3B +3FFFC01FFFE0486D4813F0B515F8A26C16F06C496C13E0D807E0C7EA3F00A26D5C000315 +7EA56D14FE00015DEC0F80EC1FC0EC3FE0A33A00FC7FF1F8A2147DA2ECFDF9017C5C14F8 +A3017E13FBA290393FF07FE0A3ECE03FA2011F5C90390F800F802D277FA630>I<3A3FFF +81FFFC4801C37FB580A26C5D6C01815BC648C66CC7FC137FEC80FE90383F81FC90381FC3 +F8EB0FE3ECE7F06DB45A6D5B7F6D5B92C8FC147E147F5C497F81903803F7E0EB07E79038 +0FE3F0ECC1F890381F81FC90383F80FE90387F007E017E137F01FE6D7E48486D7E267FFF +80B5FCB500C1148014E3A214C16C0180140029277DA630>I<3B3FFFC07FFF80486DB512 +C0B515E0A26C16C06C496C13803B01FC0003F000A2000014076D5C137E150F017F5C7F15 +1FD91F805BA214C0010F49C7FCA214E00107137EA2EB03F0157C15FCEB01F85DA2EB00F9 +ECFDF0147D147FA26E5AA36E5AA35DA2143F92C8FCA25C147EA2000F13FE486C5AEA3FC1 +EBC3F81387EB8FF0EBFFE06C5B5C6C90C9FC6C5AEA01F02B3C7EA630>I<001FB612FC48 +15FE5AA316FC90C7EA0FF8ED1FF0ED3FE0ED7FC0EDFF80003E491300C7485A4A5A4A5A4A +5A4A5A4A5A4A5A4990C7FC495A495A495A495A495A495A4948133E4890C7127F485A485A +485A485A485A48B7FCB8FCA46C15FE28277DA630>II125 D E /Fl 2 16 df13 +D15 +D E /Fm 86 125 df<4AB4EB0FE0021F9038E03FFC913A7F00F8FC1ED901FC90383FF03F +D907F090397FE07F80494801FF13FF4948485BD93F805C137F0200ED7F00EF003E01FE6D +91C7FC82ADB97EA3C648C76CC8FCB3AE486C4A7E007FD9FC3FEBFF80A339407FBF35>11 +D<4AB4FC021F13C091387F01F0903901FC0078D907F0131C4948133E494813FF49485A13 +7F1400A213FE6F5A163893C7FCAA167FB8FCA33900FE00018182B3AC486CECFF80007FD9 +FC3F13FEA32F407FBF33>I<4AB47E021F13F791387F00FFEB01F8903807F001EB0FE0EB +1FC0EB3F80137F14008101FE80AEB8FCA3C648C77EB3AE486CECFF80007FD9FC3F13FEA3 +2F407FBF33>I<4AB4ECFF80021FD9C00F13E0913B7F01F03F80F8903C01F80078FE003C +D907F0D93FF8130E49484948131F49484948EB7F804948484913FF137F02005CA201FE92 +C7FC6FED7F0070141C96C7FCAAF13F80BBFCA3C648C76CC7FC197F193FB3AC486C4A6CEB +7FC0007FD9FC3FD9FE1FB5FCA348407FBF4C>I<121EEA7F80EAFFC0A9EA7F80ACEA3F00 +AC121EAB120CC7FCA8121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A4179C019>33 +D<001E130F397F803FC000FF137F01C013E0A201E013F0A3007F133F391E600F30000013 +00A401E01370491360A3000114E04913C00003130101001380481303000EEB070048130E +0018130C0038131C003013181C1C7DBE2D>I<4B6C130C4B6C131EA20307143EA24C133C +A2030F147CA293C71278A24B14F8A2031E5CA2033E1301A2033C5CA3037C1303A203785C +A203F81307A24B5CA20201140F007FBAFCBB1280A26C1900C72707C0003EC8FC4B133CA3 +020F147CA292C71278A24A14F8A2021E5CA3023E1301007FBAFCBB1280A26C1900C727F8 +0007C0C8FC4A5CA20101140FA24A91C9FCA301035CA24A131EA20107143EA24A133CA201 +0F147CA291C71278A34914F8A2011E5CA2013E1301A2013C5CA201186D5A41517BBE4C> +I<14E0A4EB07FC90383FFF8090B512E03901F8E3F03903E0E0FCD807C0133CD80F807FD8 +1F007F003E80003C1580007C140316C00078141F00F8143F157FA47EED3F806CEC0E0092 +C7FC127F138013C0EA3FF013FEEA1FFF6C13FC6C13FF6C14C06C806C6C13F8011F7F1303 +01007FECE7FF14E102E01380157F153FED1FC0A2003E140F127FD8FF801307A5130000FC +158000F0140F1270007815005D6C141E153E6C5C6C5C3907C0E1F03903F8EFE0C6B51280 +D93FFEC7FCEB0FF8EB00E0A422497BC32D>I<013F4C7ED9FFC04B7E2601E0E015072607 +C070150F48486C4B5A023E4BC7FC48486C5D48D90FC0EB01FE003ED90EF0EB07FCDA0F3F +133E007E903A070FFFF8F8007C0200EBC1F0EE000300FC6D6C495A604D5A171F95C8FC17 +3E177E177C5F16015F007C4948485A1607007E5E003E49495A020E131F003F93C9FC6C49 +133E260F803C137E0238137C6C6C485B3901E0E0016CB448485AD93F0049133F90C74848 +EBFFC0030F903801E0E093398007C0704B4848487E4B153C033E90381F001C4B497F03FC +133E4B150F4A48017E7F0203147C5D4A4801FCEB0380140F5D4AC7FC5C143E5C14FC5C49 +5A13034948027CEB07005C4948147E011F033E5B91C8140E013E153F017E6F5B017C9238 +0F803C4917380001706C5A49923801E0E0496FB45A6C48043FC7FC41497BC34C>I +I<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A312011380120313005A +120E5A1218123812300B1C79BE19>I<1430147014E0EB01C0EB03801307EB0F00131E13 +3E133C5B13F85B12015B1203A2485AA2120F5BA2121F90C7FCA25AA3123E127EA6127C12 +FCB2127C127EA6123E123FA37EA27F120FA27F1207A26C7EA212017F12007F13787F133E +131E7FEB07801303EB01C0EB00E014701430145A77C323>I<12C07E12707E7E121E7E6C +7E7F12036C7E7F12007F1378137CA27FA2133F7FA21480130FA214C0A3130714E0A61303 +14F0B214E01307A614C0130FA31480A2131F1400A25B133EA25BA2137813F85B12015B48 +5A12075B48C7FC121E121C5A5A5A5A145A7BC323>II<121EEA7F8012FF13C0A213E0A312 +7FEA1E601200A413E013C0A312011380120313005A120E5A1218123812300B1C798919> +44 DI<121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A0A798919> +IIIIII<150E151E153EA2157EA215FE1401A21403EC077E14 +06140E141CA214381470A214E0EB01C0A2EB0380EB0700A2130E5BA25B5BA25B5B120148 +5A90C7FC5A120E120C121C5AA25A5AB8FCA3C8EAFE00AC4A7E49B6FCA3283E7EBD2D>I< +00061403D80780131F01F813FE90B5FC5D5D5D15C092C7FC14FCEB3FE090C9FCACEB01FE +90380FFF8090383E03E090387001F8496C7E49137E497F90C713800006141FC813C0A216 +E0150FA316F0A3120C127F7F12FFA416E090C7121F12FC007015C012780038EC3F80123C +6CEC7F00001F14FE6C6C485A6C6C485A3903F80FE0C6B55A013F90C7FCEB07F8243F7CBC +2D>II<1238123C123F90B612FCA3 +16F85A16F016E00078C712010070EC03C0ED078016005D48141E151C153C5DC8127015F0 +4A5A5D14034A5A92C7FC5C141EA25CA2147C147814F8A213015C1303A31307A3130F5CA2 +131FA6133FAA6D5A0107C8FC26407BBD2D>III<121EEA7F +80A2EAFFC0A4EA7F80A2EA1E00C7FCB3121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A2779 +A619>I<121EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3121E127FEAFF80A213C0A412 +7F121E1200A412011380A3120313005A1206120E120C121C5A1230A20A3979A619>I<15 +074B7EA34B7EA34B7EA34B7EA34B7E15E7A2913801C7FC15C3A291380381FEA34AC67EA3 +020E6D7EA34A6D7EA34A6D7EA34A6D7EA34A6D7EA349486D7E91B6FCA249819138800001 +A249C87EA24982010E157FA2011E82011C153FA2013C820138151FA2017882170F13FC00 +034C7ED80FFF4B7EB500F0010FB512F8A33D417DC044>65 DI< +DB3FF01306912603FFFE130E020F9038FF801E913A3FF007E03E9139FF8000F8D903FEC7 +EA7C7ED907F8EC1EFE4948140FD93FE0140749481403495A91C812014848150012034848 +167E5B000F173EA24848161EA2123F5B180E127FA349160012FFAC127F7F180EA2123FA2 +7F001F171E181C6C7EA20007173C6D16386C6C1678000117706C6C16F06EEC01E06D6C15 +C06D6C1403D90FF0EC07806D6CEC1F00D903FE143E902600FF8013F891393FF007F0020F +B512C0020391C7FC9138003FF037427BBF42>IIIIIII<011FB512FCA3D9000713006E5A1401B3B3A6123FEA7F80EAFFC0A44A5A1380D87F +005B007C130700385C003C495A6C495A6C495A2603E07EC7FC3800FFF8EB3FC026407CBD +2F>III< +B500C093383FFFF0A300016D93387FF800D8007F18E0D977F016EFA3D973F8ED01CFA2D9 +71FCED038FA3D970FEED070FA26E150E80A26E6C141CA36E6C1438A26E6C1470A36E6C14 +E0A26E6CEB01C0A36E6CEB0380A36E6CEB0700A2037F130EA36F6C5AA26F6C5AA36F6C5A +A25FED07F0A2923803F9C0A36FB45AA26F90C7FCA213F8486C147ED807FFEF3FF8B500F8 +013C011FB512F0A34C3E7DBD53>IIIIIII<003FB91280A3903AF0007FE001018090393FC0003F +48C7ED1FC0007E1707127C00781703A300701701A548EF00E0A5C81600B3B14B7E4B7E01 +07B612FEA33B3D7DBC42>IIII<007FB5D8C003B512E0A3C649C7EB +FC00D93FF8EC3FE06D48EC1F806D6C92C7FC171E6D6C141C6D6C143C5F6D6C14706D6D13 +F04C5ADA7FC05B023F13036F485ADA1FF090C8FC020F5BEDF81E913807FC1C163C6E6C5A +913801FF7016F06E5B6F5AA26F7E6F7EA28282153FED3BFEED71FF15F103E07F913801C0 +7F0203804B6C7EEC07004A6D7E020E6D7E5C023C6D7E02386D7E14784A6D7E4A6D7F1301 +49486E7E4A6E7E130749C86C7E496F7E497ED9FFC04A7E00076DEC7FFFB500FC0103B512 +FEA33F3E7EBD44>II91 D<486C13C00003130101001380481303000E +EB070048130E0018130C0038131C003013180070133800601330A300E01370481360A400 +CFEB678039FFC07FE001E013F0A3007F133FA2003F131F01C013E0390F0007801C1C73BE +2D>II96 DII<49B4FC010F13E090383F00F8017C131E4848131F4848137F0007ECFF80485A5B +121FA24848EB7F00151C007F91C7FCA290C9FC5AAB6C7EA3003FEC01C07F001F14031680 +6C6C13076C6C14000003140E6C6C131E6C6C137890383F01F090380FFFC0D901FEC7FC22 +2A7DA828>IIII<167C903903F801FF903A1FFF078F8090397E0F +DE1F9038F803F83803F001A23B07E000FC0600000F6EC7FC49137E001F147FA8000F147E +6D13FE00075C6C6C485AA23901F803E03903FE0FC026071FFFC8FCEB03F80006CAFC120E +A3120FA27F7F6CB512E015FE6C6E7E6C15E06C810003813A0FC0001FFC48C7EA01FE003E +140048157E825A82A46C5D007C153E007E157E6C5D6C6C495A6C6C495AD803F0EB0FC0D8 +00FE017FC7FC90383FFFFC010313C0293D7EA82D>III<1478EB +01FEA2EB03FFA4EB01FEA2EB00781400AC147FEB7FFFA313017F147FB3B3A5123E127F38 +FF807E14FEA214FCEB81F8EA7F01387C03F0381E07C0380FFF803801FC00185185BD1C> +III<2701F801FE14FF00FF90 +2707FFC00313E0913B1E07E00F03F0913B7803F03C01F80007903BE001F87000FC2603F9 +C06D487F000101805C01FBD900FF147F91C75B13FF4992C7FCA2495CB3A6486C496CECFF +80B5D8F87FD9FC3F13FEA347287DA74C>I<3901F801FE00FF903807FFC091381E07E091 +387803F000079038E001F82603F9C07F0001138001FB6D7E91C7FC13FF5BA25BB3A6486C +497EB5D8F87F13FCA32E287DA733>I<14FF010713E090381F81F890387E007E01F8131F +4848EB0F804848EB07C04848EB03E0000F15F04848EB01F8A2003F15FCA248C812FEA448 +15FFA96C15FEA36C6CEB01FCA3001F15F86C6CEB03F0A26C6CEB07E06C6CEB0FC06C6CEB +1F80D8007EEB7E0090383F81FC90380FFFF0010090C7FC282A7EA82D>I<3901FC03FC00 +FF90381FFF8091387C0FE09039FDE003F03A03FFC001FC6C496C7E91C7127F49EC3F805B +EE1FC017E0A2EE0FF0A3EE07F8AAEE0FF0A4EE1FE0A2EE3FC06D1580EE7F007F6E13FE91 +38C001F89039FDE007F09039FC780FC0DA3FFFC7FCEC07F891C9FCAD487EB512F8A32D3A +7EA733>I<02FF131C0107EBC03C90381F80F090397F00387C01FC131CD803F8130E4848 +EB0FFC150748481303121F485A1501485AA448C7FCAA6C7EA36C7EA2001F14036C7E1507 +6C6C130F6C7E6C6C133DD8007E137990383F81F190380FFFC1903801FE0190C7FCAD4B7E +92B512F8A32D3A7DA730>I<3901F807E000FFEB1FF8EC787CECE1FE3807F9C100031381 +EA01FB1401EC00FC01FF1330491300A35BB3A5487EB512FEA31F287EA724>I<90383FC0 +603901FFF8E03807C03F381F000F003E1307003C1303127C0078130112F81400A27E7E7E +6D1300EA7FF8EBFFC06C13F86C13FE6C7F6C1480000114C0D8003F13E0010313F0EB001F +EC0FF800E01303A214017E1400A27E15F07E14016C14E06CEB03C0903880078039F3E01F +0038E0FFFC38C01FE01D2A7DA824>I<131CA6133CA4137CA213FCA2120112031207001F +B512C0B6FCA2D801FCC7FCB3A215E0A912009038FE01C0A2EB7F03013F138090381F8700 +EB07FEEB01F81B397EB723>IIII +II<001F +B61280A2EBE0000180140049485A001E495A121C4A5A003C495A141F00385C4A5A147F5D +4AC7FCC6485AA2495A495A130F5C495A90393FC00380A2EB7F80EBFF005A5B4848130712 +07491400485A48485BA248485B4848137F00FF495A90B6FCA221277EA628>I124 D E /Fn 20 122 df<13FF000313E0487F001F13FC487F805A1580B6 +12C0A315E0A315F0A37EA27EA27E000713F36C13E3C61383EB00031407A215E0A3140FA2 +15C0141FA2EC3F80A2147F15005C5C1301495A5C1307495A495A133F495A495A4890C7FC +485A485A485A5B6C5AEA01801C3A72F736>39 D69 DI<96267FFFE01670063FB6ED01F80503B7 +00F01403053F04FC14074CB96C130F040706E0131F043F72133F93BA00FC137F0303DC00 +076D13FF030F03C09039003FFF814B02FCC8000713C3037F02E0030113F792B600806F6C +B5FC02034ACA121F4A02F8834A02E0834A4A1701027F4A8391B548CC7E494A85495C4C85 +4988494A85494A85495C8A4991CDFC90B54886A2484A1B7FA2481E3F5D481E1F5D5A1F0F +A2485CA3481E075DA2795A489BC9FCA45DA2B6FCB27EA26F0403BA12C0A47EA3816C96C8 +000302F8C7FCA36C80A36C80A27E817E817E817F6D80827F6D806D806D80826D6E606D80 +6E80021F6E5F6E02F05F6E806E02FE5F0200DAFFC05E6F02F04BB6FC031F02FE030713CF +6FDAFFE0021F138703039226FF8003B51201030093B6EAFC00043F4E133F040706E0131F +04014E1307DC003F4CC71201050304F8EC0070DD003F038092C8FCDE007F01F0CCFC827A +75F798>I78 D80 D82 D85 D<97380FFFE00607B6FCA8F00003190086B3AD93383FFF800307B5 +12F8033F14FF4AB712C0020716F0021F16FC027F9039FE007FFE91B500F0EB0FFF010302 +80010190B5FC4949C87E49498149498149498149498190B548814884484A8192CAFC5AA2 +485BA25A5C5AA35A5CA4B5FCAF7EA4807EA37EA2807EA26C7F616C6E5D6C606C80616D6D +5D6D6D5D6D6D92B67E6D6D4A15FC010301FF0207EDFFFE6D02C0EB3FFE6D6C9039FC01FF +F86E90B65A020F16C002031600DA007F14FC030F14E09226007FFEC749C7FC5F797AF76C +>100 D<93387FFF80030FB512FC037FECFF804AB712E0020716F8021F16FE027FD9F807 +7F49B5D8C000804991C7003F13E04901FC020F7F49496E7F49498049496E7F49496E7F90 +B55A48727E92C914804884485B1BC048841BE0485BA27313F05AA25C5AA21BF885A2B5FC +A391BAFCA41BF002F8CCFCA67EA3807EA47E806CF103F0F207F86C7F1A0F6C6E17F06C19 +1F6F17E06C6E163F6D6DEE7FC06D6D16FF6D6D4B13806D6D4B13006D6D6CEC0FFE6D02E0 +EC3FFC6D02F8ECFFF86D9126FFC00F5B023F91B65A020F178002034CC7FC020016F8031F +15E0030392C8FCDB000F13E04D507BCE58>II<903801FFFCB6FC +A8C67E131F7FB3AD95380FFFE095B512FE05036E7E050F15E0053F15F84D81932701FFF0 +1F7F4CD900077FDC07FC6D80DC0FF06D80DC1FC07F4C48824CC8FC047E6F7F5EEDFDF85E +03FF707F5EA25EA25EA293C9FCA45DB3B3A6B8D8E003B81280A8617879F76C>104 +DI<903801FFFCB6FCA8C67E131F7FB3B3B3B3B3ABB812C0A82A7879F735> +108 D<93381FFFE00303B6FC031F15E092B712FC020316FF020F17C0023FD9FC0014F091 +B500C0010F13FC4991C700037F4901FC02007F010F496F13C049496F7F49496F7F4B8149 +496F7F90B5C96C7F4886A24849707F481B80A248497014C0A2481BE0A348497113F0A348 +1BF8A5B51AFCAE6C1BF8A46C1BF06E94B5FCA36C1BE0A26C6D4C14C0A26C1B806E5E6C1B +006C6E4B5BA26C6E4B5B6D6D4B5B6D6D4B5B6D6D4B5B6D6D92B55A6D01FF02035C6D02C0 +010F91C7FC010002FC90B512FC6E90B75A021F17E00207178002014CC8FCDA003F15F003 +0392C9FCDB001F13E056507BCE61>111 D<902601FFF8EB07FEB691383FFFC094B512F0 +0403804C14FE4C8093261FFC3F138093263FE07F13C0DC7F80B5FCC66C5D011FDAFE0114 +E06DEBF9FC16F815FB16F016E015FF16C07114C05E72138095381FFE0093C76C5AF001E0 +95C8FCA25DA65DB3B3A2B812F8A8434E7ACD4F>114 D<912603FFFCEB0780027F9039FF +E00FC00103B6EAF83F010FEDFEFF013F92B5FC49EB000F2601FFF01300480180143F4890 +C8120F4848814848814981123F83485A187FA212FF6D163FA37F7F6DEE1F8002C092C7FC +14F014FEECFFF06CECFF8016FEEEFFE06C16FC6C16FF18C06C836C17F86C836C836C8301 +3F17806D17C0010717E0010117F0EB003F020716F8EC001F030015FC1607EE007F051F13 +FE1707007E82B482836D167FA2183F7F181FA27F19FC7FA26D163F6D17F86D167F19F06D +16FF6E4A13E002E04A13C06E4A138002FE023F1300913AFFC003FFFE01E790B65A01C316 +F0018016C026FE003F92C7FC48010714F80070D9007F90C8FC3F507ACE4C>I<15FFA75C +A55CA45CA25CA25CA25CA25C91B5FCA25B5B5B131F5B90B9FC120FBAFCA6D8000791C9FC +B3B3A3F01FE0AE183F7014C07F187F7014806D16FF826D4B13006E6D485AEEFE0F6E90B5 +5A020F5D6E5D020115C06E6C5C031F49C7FC030113F03B6E7CEC4B>II121 D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 1401 1386 a Fn(User's)66 b(Guide)1665 1760 y(for)e(the)1041 +2133 y(GNU)h(GPERF)h(Utilit)-5 b(y)1553 2756 y Fm(Douglas)30 +b(C.)h(Sc)m(hmidt)1417 3254 y(last)f(up)s(dated)f(14)i(April)d(1998) +1668 3503 y(for)i(v)m(ersion)g(2.7)p eop +%%Page: 2 2 +2 1 bop 0 3629 a Fm(Cop)m(yrigh)m(t)452 3626 y(c)427 +3629 y Fl(\015)30 b Fm(1989-1998)k(F)-8 b(ree)32 b(Soft)m(w)m(are)f(F) +-8 b(oundation,)31 b(Inc.)0 3903 y(P)m(ermission)23 b(is)h(gran)m(ted)h +(to)h(mak)m(e)g(and)e(distribute)e(v)m(erbatim)j(copies)f(of)h(this)f +(man)m(ual)g(pro)m(vided)g(the)h(cop)m(yrigh)m(t)0 4027 +y(notice)31 b(and)e(this)h(p)s(ermission)d(notice)k(are)f(preserv)m(ed) +g(on)h(all)e(copies.)0 4301 y(P)m(ermission)d(is)h(gran)m(ted)i(to)g +(cop)m(y)f(and)g(distribute)d(mo)s(di\014ed)h(v)m(ersions)h(of)i(this)d +(man)m(ual)i(under)e(the)i(conditions)0 4426 y(for)21 +b(v)m(erbatim)g(cop)m(ying,)i(pro)m(vided)c(also)j(that)f(the)g +(section)h(en)m(titled)e(\\GNU)i Fk(gperf)e Fm(General)h(Public)e +(License")i(is)0 4550 y(included)f(exactly)k(as)g(in)e(the)h(original,) +g(and)g(pro)m(vided)f(that)h(the)h(en)m(tire)f(resulting)e(deriv)m(ed)h +(w)m(ork)i(is)e(distributed)0 4675 y(under)29 b(the)h(terms)h(of)f(a)h +(p)s(ermission)c(notice)k(iden)m(tical)e(to)i(this)e(one.)0 +4949 y(P)m(ermission)37 b(is)h(gran)m(ted)i(to)g(cop)m(y)g(and)f +(distribute)d(translations)i(of)h(this)f(man)m(ual)h(in)m(to)g(another) +g(language,)0 5073 y(under)f(the)h(ab)s(o)m(v)m(e)i(conditions)c(for)i +(mo)s(di\014ed)e(v)m(ersions,)k(except)g(that)f(the)f(section)g(en)m +(titled)g(\\GNU)h Fk(gperf)0 5198 y Fm(General)28 b(Public)e(License")j +(ma)m(y)g(b)s(e)e(included)f(in)h(a)i(translation)e(appro)m(v)m(ed)i(b) +m(y)f(the)g(author)h(instead)e(of)i(in)e(the)0 5322 y(original)i +(English.)p eop +%%Page: 1 3 +1 2 bop 0 -116 a Fm(GNU)31 b(GENERAL)f(PUBLIC)h(LICENSE)2352 +b(1)0 366 y Fj(GNU)30 b(GENERAL)h(PUBLIC)f(LICENSE)1453 +615 y Fm(V)-8 b(ersion)30 b(1,)h(F)-8 b(ebruary)30 b(1989)240 +874 y(Cop)m(yrigh)m(t)692 871 y(c)667 874 y Fl(\015)g +Fm(1989)i(F)-8 b(ree)32 b(Soft)m(w)m(are)f(F)-8 b(oundation,)31 +b(Inc.)240 978 y(675)h(Mass)e(Av)m(e,)i(Cam)m(bridge,)e(MA)h(02139,)h +(USA)240 1185 y(Ev)m(ery)m(one)f(is)f(p)s(ermitted)f(to)i(cop)m(y)g +(and)f(distribute)e(v)m(erbatim)i(copies)240 1289 y(of)h(this)e +(license)g(do)s(cumen)m(t,)i(but)e(c)m(hanging)i(it)f(is)f(not)i(allo)m +(w)m(ed.)0 1792 y Fi(Pream)l(ble)125 2072 y Fm(The)40 +b(license)g(agreemen)m(ts)j(of)e(most)g(soft)m(w)m(are)h(companies)f +(try)g(to)h(k)m(eep)f(users)f(at)i(the)f(mercy)g(of)g(those)0 +2196 y(companies.)e(By)26 b(con)m(trast,)i(our)d(General)g(Public)e +(License)j(is)e(in)m(tended)h(to)h(guaran)m(tee)h(y)m(our)e(freedom)h +(to)g(share)0 2321 y(and)34 b(c)m(hange)i(free)e(soft)m(w)m(are|to)j +(mak)m(e)e(sure)f(the)h(soft)m(w)m(are)h(is)d(free)i(for)f(all)g(its)g +(users.)52 b(The)34 b(General)g(Public)0 2446 y(License)24 +b(applies)e(to)j(the)f(F)-8 b(ree)25 b(Soft)m(w)m(are)g(F)-8 +b(oundation's)24 b(soft)m(w)m(are)i(and)d(to)i(an)m(y)f(other)h +(program)e(whose)h(authors)0 2570 y(commit)30 b(to)h(using)e(it.)41 +b(Y)-8 b(ou)30 b(can)h(use)f(it)g(for)g(y)m(our)h(programs,)f(to)s(o.) +125 2850 y(When)c(w)m(e)h(sp)s(eak)g(of)g(free)g(soft)m(w)m(are,)i(w)m +(e)e(are)g(referring)f(to)h(freedom,)h(not)f(price.)38 +b(Sp)s(eci\014cally)-8 b(,)26 b(the)h(General)0 2975 +y(Public)32 b(License)j(is)e(designed)h(to)h(mak)m(e)h(sure)e(that)h(y) +m(ou)h(ha)m(v)m(e)f(the)g(freedom)g(to)g(giv)m(e)h(a)m(w)m(a)m(y)g(or)f +(sell)e(copies)i(of)0 3099 y(free)h(soft)m(w)m(are,)k(that)c(y)m(ou)h +(receiv)m(e)g(source)f(co)s(de)g(or)h(can)f(get)h(it)f(if)f(y)m(ou)h(w) +m(an)m(t)h(it,)h(that)f(y)m(ou)f(can)g(c)m(hange)i(the)0 +3224 y(soft)m(w)m(are)32 b(or)e(use)g(pieces)g(of)h(it)f(in)f(new)h +(free)g(programs;)h(and)e(that)i(y)m(ou)g(kno)m(w)f(y)m(ou)h(can)g(do)f +(these)h(things.)125 3504 y(T)-8 b(o)27 b(protect)h(y)m(our)f(righ)m +(ts,)h(w)m(e)f(need)g(to)h(mak)m(e)g(restrictions)e(that)h(forbid)f(an) +m(y)m(one)i(to)g(den)m(y)f(y)m(ou)g(these)g(righ)m(ts)0 +3628 y(or)g(to)i(ask)e(y)m(ou)h(to)g(surrender)e(the)h(righ)m(ts.)39 +b(These)28 b(restrictions)e(translate)h(to)i(certain)e(resp)s +(onsibilities)22 b(for)28 b(y)m(ou)0 3753 y(if)h(y)m(ou)i(distribute)d +(copies)i(of)h(the)f(soft)m(w)m(are,)i(or)f(if)e(y)m(ou)i(mo)s(dify)d +(it.)125 4033 y(F)-8 b(or)30 b(example,)f(if)g(y)m(ou)h(distribute)d +(copies)i(of)h(a)f(suc)m(h)h(a)f(program,)h(whether)f(gratis)g(or)h +(for)f(a)h(fee,)g(y)m(ou)g(m)m(ust)0 4157 y(giv)m(e)h(the)g(recipien)m +(ts)f(all)f(the)i(righ)m(ts)f(that)h(y)m(ou)g(ha)m(v)m(e.)43 +b(Y)-8 b(ou)31 b(m)m(ust)g(mak)m(e)g(sure)f(that)h(they)-8 +b(,)32 b(to)s(o,)g(receiv)m(e)f(or)g(can)0 4282 y(get)h(the)e(source)h +(co)s(de.)41 b(And)29 b(y)m(ou)i(m)m(ust)f(tell)g(them)g(their)f(righ)m +(ts.)125 4562 y(W)-8 b(e)30 b(protect)g(y)m(our)e(righ)m(ts)h(with)e(t) +m(w)m(o)k(steps:)40 b(\(1\))30 b(cop)m(yrigh)m(t)f(the)g(soft)m(w)m +(are,)i(and)d(\(2\))i(o\013er)g(y)m(ou)f(this)f(license)0 +4686 y(whic)m(h)h(giv)m(es)i(y)m(ou)g(legal)f(p)s(ermission)d(to)k(cop) +m(y)-8 b(,)32 b(distribute)c(and/or)i(mo)s(dify)f(the)h(soft)m(w)m +(are.)125 4966 y(Also,)d(for)g(eac)m(h)h(author's)f(protection)g(and)f +(ours,)h(w)m(e)h(w)m(an)m(t)f(to)h(mak)m(e)g(certain)f(that)g(ev)m(ery) +m(one)i(understands)0 5091 y(that)37 b(there)f(is)f(no)h(w)m(arran)m(t) +m(y)h(for)f(this)f(free)i(soft)m(w)m(are.)59 b(If)36 +b(the)g(soft)m(w)m(are)i(is)d(mo)s(di\014ed)f(b)m(y)i(someone)h(else)f +(and)0 5215 y(passed)j(on,)j(w)m(e)e(w)m(an)m(t)g(its)f(recipien)m(ts)g +(to)h(kno)m(w)f(that)i(what)e(they)h(ha)m(v)m(e)g(is)f(not)h(the)f +(original,)i(so)e(that)i(an)m(y)0 5340 y(problems)29 +b(in)m(tro)s(duced)f(b)m(y)j(others)f(will)e(not)j(re\015ect)g(on)f +(the)g(original)f(authors')h(reputations.)p eop +%%Page: 2 4 +2 3 bop 0 -116 a Fm(2)2965 b(User's)31 b(Guide)e(to)i +Fk(gperf)125 366 y Fm(The)e(precise)h(terms)g(and)g(conditions)f(for)h +(cop)m(ying,)h(distribution)26 b(and)k(mo)s(di\014cation)f(follo)m(w.)0 +911 y Fi(TERMS)h(AND)g(CONDITIONS)49 1195 y Fm(1.)61 +b(This)28 b(License)i(Agreemen)m(t)i(applies)c(to)j(an)m(y)g(program)f +(or)g(other)h(w)m(ork)f(whic)m(h)f(con)m(tains)h(a)h(notice)f(placed) +180 1320 y(b)m(y)k(the)h(cop)m(yrigh)m(t)g(holder)e(sa)m(ying)h(it)g +(ma)m(y)h(b)s(e)f(distributed)d(under)i(the)i(terms)f(of)h(this)e +(General)h(Public)180 1444 y(License.)53 b(The)34 b(\\Program",)k(b)s +(elo)m(w,)d(refers)f(to)i(an)m(y)f(suc)m(h)f(program)g(or)h(w)m(ork,)h +(and)e(a)h(\\w)m(ork)h(based)e(on)180 1569 y(the)d(Program")h(means)f +(either)g(the)h(Program)f(or)g(an)m(y)h(w)m(ork)f(con)m(taining)g(the)h +(Program)f(or)g(a)h(p)s(ortion)e(of)180 1693 y(it,)g(either)g(v)m +(erbatim)g(or)g(with)g(mo)s(di\014cations.)38 b(Eac)m(h)31 +b(licensee)f(is)g(addressed)f(as)i(\\y)m(ou".)49 1853 +y(2.)61 b(Y)-8 b(ou)41 b(ma)m(y)g(cop)m(y)h(and)e(distribute)e(v)m +(erbatim)i(copies)h(of)g(the)g(Program's)f(source)h(co)s(de)g(as)g(y)m +(ou)g(receiv)m(e)180 1978 y(it,)36 b(in)e(an)m(y)h(medium,)g(pro)m +(vided)f(that)h(y)m(ou)h(conspicuously)d(and)h(appropriately)g(publish) +d(on)k(eac)m(h)h(cop)m(y)180 2102 y(an)h(appropriate)g(cop)m(yrigh)m(t) +g(notice)h(and)f(disclaimer)e(of)i(w)m(arran)m(t)m(y;)42 +b(k)m(eep)c(in)m(tact)g(all)e(the)i(notices)f(that)180 +2227 y(refer)d(to)i(this)e(General)g(Public)f(License)h(and)g(to)i(the) +f(absence)g(of)g(an)m(y)g(w)m(arran)m(t)m(y;)j(and)c(giv)m(e)i(an)m(y)f +(other)180 2351 y(recipien)m(ts)29 b(of)h(the)g(Program)g(a)g(cop)m(y)g +(of)g(this)f(General)h(Public)d(License)i(along)h(with)f(the)h +(Program.)40 b(Y)-8 b(ou)180 2476 y(ma)m(y)31 b(c)m(harge)h(a)e(fee)h +(for)f(the)h(ph)m(ysical)e(act)i(of)g(transferring)e(a)h(cop)m(y)-8 +b(.)49 2636 y(3.)61 b(Y)-8 b(ou)45 b(ma)m(y)f(mo)s(dify)f(y)m(our)h +(cop)m(y)h(or)f(copies)g(of)g(the)g(Program)g(or)g(an)m(y)h(p)s(ortion) +e(of)h(it,)j(and)d(cop)m(y)h(and)180 2761 y(distribute)24 +b(suc)m(h)i(mo)s(di\014cations)f(under)g(the)i(terms)f(of)h(P)m +(aragraph)g(1)g(ab)s(o)m(v)m(e,)h(pro)m(vided)e(that)h(y)m(ou)g(also)f +(do)180 2885 y(the)31 b(follo)m(wing:)255 3045 y Fl(\017)60 +b Fm(cause)30 b(the)g(mo)s(di\014ed)e(\014les)h(to)h(carry)g(prominen)m +(t)e(notices)i(stating)g(that)g(y)m(ou)h(c)m(hanged)f(the)g(\014les)f +(and)360 3170 y(the)i(date)g(of)f(an)m(y)h(c)m(hange;)h(and)255 +3330 y Fl(\017)60 b Fm(cause)43 b(the)g(whole)f(of)h(an)m(y)g(w)m(ork)g +(that)h(y)m(ou)f(distribute)d(or)j(publish,)f(that)h(in)f(whole)g(or)h +(in)e(part)360 3454 y(con)m(tains)g(the)f(Program)h(or)g(an)m(y)f(part) +h(thereof,)j(either)c(with)f(or)h(without)g(mo)s(di\014cations,)h(to)h +(b)s(e)360 3579 y(licensed)32 b(at)j(no)f(c)m(harge)h(to)g(all)d(third) +h(parties)g(under)f(the)i(terms)g(of)g(this)f(General)h(Public)d +(License)360 3703 y(\(except)g(that)f(y)m(ou)g(ma)m(y)g(c)m(ho)s(ose)g +(to)g(gran)m(t)g(w)m(arran)m(t)m(y)h(protection)f(to)g(some)g(or)f(all) +f(third)g(parties,)h(at)360 3828 y(y)m(our)h(option\).)255 +3988 y Fl(\017)60 b Fm(If)24 b(the)g(mo)s(di\014ed)e(program)i +(normally)f(reads)h(commands)g(in)m(teractiv)m(ely)g(when)f(run,)i(y)m +(ou)f(m)m(ust)g(cause)360 4113 y(it,)34 b(when)f(started)i(running)c +(for)i(suc)m(h)h(in)m(teractiv)m(e)g(use)g(in)e(the)i(simplest)e(and)h +(most)i(usual)d(w)m(a)m(y)-8 b(,)36 b(to)360 4237 y(prin)m(t)29 +b(or)h(displa)m(y)e(an)i(announcemen)m(t)g(including)c(an)k +(appropriate)f(cop)m(yrigh)m(t)i(notice)f(and)f(a)i(notice)360 +4362 y(that)c(there)f(is)f(no)g(w)m(arran)m(t)m(y)i(\(or)f(else,)h(sa)m +(ying)f(that)h(y)m(ou)f(pro)m(vide)f(a)h(w)m(arran)m(t)m(y\))h(and)f +(that)g(users)f(ma)m(y)360 4486 y(redistribute)j(the)j(program)g(under) +e(these)i(conditions,)f(and)g(telling)f(the)i(user)g(ho)m(w)f(to)i +(view)e(a)h(cop)m(y)360 4611 y(of)g(this)e(General)h(Public)e(License.) +255 4771 y Fl(\017)60 b Fm(Y)-8 b(ou)38 b(ma)m(y)g(c)m(harge)h(a)f(fee) +g(for)f(the)h(ph)m(ysical)e(act)j(of)e(transferring)f(a)i(cop)m(y)-8 +b(,)41 b(and)c(y)m(ou)h(ma)m(y)g(at)g(y)m(our)360 4895 +y(option)30 b(o\013er)h(w)m(arran)m(t)m(y)g(protection)g(in)e(exc)m +(hange)j(for)e(a)g(fee.)180 5091 y(Mere)22 b(aggregation)h(of)f +(another)g(indep)s(enden)m(t)d(w)m(ork)j(with)e(the)h(Program)h(\(or)g +(its)f(deriv)-5 b(ativ)m(e\))21 b(on)g(a)h(v)m(olume)180 +5215 y(of)36 b(a)g(storage)h(or)f(distribution)c(medium)h(do)s(es)j +(not)g(bring)e(the)h(other)h(w)m(ork)g(under)e(the)i(scop)s(e)g(of)f +(these)180 5340 y(terms.)p eop +%%Page: 3 5 +3 4 bop 0 -116 a Fm(GNU)31 b(GENERAL)f(PUBLIC)h(LICENSE)2352 +b(3)49 366 y(4.)61 b(Y)-8 b(ou)33 b(ma)m(y)h(cop)m(y)f(and)g +(distribute)d(the)j(Program)g(\(or)g(a)g(p)s(ortion)f(or)h(deriv)-5 +b(ativ)m(e)32 b(of)h(it,)g(under)f(P)m(aragraph)180 491 +y(2\))j(in)e(ob)5 b(ject)36 b(co)s(de)e(or)h(executable)g(form)e(under) +g(the)i(terms)f(of)h(P)m(aragraphs)f(1)h(and)f(2)h(ab)s(o)m(v)m(e)g +(pro)m(vided)180 616 y(that)c(y)m(ou)g(also)f(do)g(one)h(of)f(the)h +(follo)m(wing:)255 762 y Fl(\017)60 b Fm(accompan)m(y)28 +b(it)d(with)g(the)i(complete)f(corresp)s(onding)e(mac)m(hine-readable)i +(source)h(co)s(de,)g(whic)m(h)e(m)m(ust)360 887 y(b)s(e)30 +b(distributed)d(under)i(the)i(terms)f(of)g(P)m(aragraphs)h(1)g(and)e(2) +i(ab)s(o)m(v)m(e;)h(or,)255 1033 y Fl(\017)60 b Fm(accompan)m(y)36 +b(it)d(with)g(a)i(written)f(o\013er,)i(v)-5 b(alid)32 +b(for)i(at)h(least)g(three)f(y)m(ears,)j(to)e(giv)m(e)g(an)m(y)f(third) +f(part)m(y)360 1158 y(free)25 b(\(except)h(for)f(a)g(nominal)e(c)m +(harge)j(for)f(the)g(cost)h(of)f(distribution\))d(a)j(complete)g(mac)m +(hine-readable)360 1282 y(cop)m(y)k(of)g(the)f(corresp)s(onding)f +(source)i(co)s(de,)g(to)g(b)s(e)f(distributed)d(under)i(the)i(terms)f +(of)h(P)m(aragraphs)g(1)360 1407 y(and)h(2)h(ab)s(o)m(v)m(e;)g(or,)255 +1553 y Fl(\017)60 b Fm(accompan)m(y)25 b(it)f(with)f(the)h(information) +e(y)m(ou)j(receiv)m(ed)f(as)h(to)g(where)e(the)h(corresp)s(onding)e +(source)j(co)s(de)360 1678 y(ma)m(y)38 b(b)s(e)f(obtained.)61 +b(\(This)36 b(alternativ)m(e)h(is)g(allo)m(w)m(ed)g(only)f(for)h +(noncommercial)g(distribution)d(and)360 1802 y(only)29 +b(if)h(y)m(ou)h(receiv)m(ed)f(the)h(program)f(in)f(ob)5 +b(ject)31 b(co)s(de)g(or)f(executable)h(form)f(alone.\))180 +1971 y(Source)41 b(co)s(de)g(for)g(a)h(w)m(ork)f(means)g(the)g +(preferred)f(form)h(of)g(the)g(w)m(ork)h(for)e(making)h(mo)s +(di\014cations)e(to)180 2095 y(it.)54 b(F)-8 b(or)35 +b(an)g(executable)h(\014le,)f(complete)g(source)g(co)s(de)g(means)g +(all)f(the)h(source)g(co)s(de)g(for)g(all)e(mo)s(dules)g(it)180 +2220 y(con)m(tains;)39 b(but,)e(as)f(a)g(sp)s(ecial)f(exception,)i(it)f +(need)f(not)h(include)e(source)i(co)s(de)g(for)g(mo)s(dules)e(whic)m(h) +h(are)180 2344 y(standard)c(libraries)d(that)k(accompan)m(y)h(the)f(op) +s(erating)e(system)i(on)f(whic)m(h)f(the)i(executable)g(\014le)f(runs,) +f(or)180 2469 y(for)g(standard)g(header)g(\014les)f(or)i(de\014nitions) +c(\014les)j(that)h(accompan)m(y)g(that)g(op)s(erating)f(system.)49 +2615 y(5.)61 b(Y)-8 b(ou)32 b(ma)m(y)h(not)f(cop)m(y)-8 +b(,)33 b(mo)s(dify)-8 b(,)31 b(sublicense,)f(distribute)g(or)h +(transfer)h(the)g(Program)f(except)i(as)f(expressly)180 +2740 y(pro)m(vided)20 b(under)g(this)g(General)h(Public)e(License.)37 +b(An)m(y)21 b(attempt)i(otherwise)d(to)i(cop)m(y)-8 b(,)25 +b(mo)s(dify)-8 b(,)22 b(sublicense,)180 2864 y(distribute)k(or)j +(transfer)e(the)i(Program)g(is)e(v)m(oid,)i(and)f(will)e(automatically) +i(terminate)h(y)m(our)f(righ)m(ts)g(to)h(use)180 2989 +y(the)34 b(Program)g(under)f(this)f(License.)51 b(Ho)m(w)m(ev)m(er,)37 +b(parties)d(who)f(ha)m(v)m(e)i(receiv)m(ed)f(copies,)h(or)f(righ)m(ts)g +(to)g(use)180 3113 y(copies,)f(from)f(y)m(ou)h(under)e(this)g(General)i +(Public)d(License)i(will)e(not)j(ha)m(v)m(e)h(their)d(licenses)h +(terminated)g(so)180 3238 y(long)e(as)h(suc)m(h)f(parties)f(remain)h +(in)f(full)f(compliance.)49 3384 y(6.)61 b(By)32 b(cop)m(ying,)h +(distributing)28 b(or)k(mo)s(difying)e(the)i(Program)g(\(or)h(an)m(y)f +(w)m(ork)g(based)g(on)g(the)g(Program\))h(y)m(ou)180 +3509 y(indicate)c(y)m(our)i(acceptance)h(of)f(this)e(license)h(to)h(do) +f(so,)h(and)f(all)f(its)h(terms)g(and)g(conditions.)49 +3655 y(7.)61 b(Eac)m(h)37 b(time)f(y)m(ou)g(redistribute)e(the)i +(Program)g(\(or)h(an)m(y)f(w)m(ork)g(based)g(on)g(the)g(Program\),)j +(the)d(recipien)m(t)180 3780 y(automatically)j(receiv)m(es)i(a)e +(license)g(from)g(the)g(original)f(licensor)g(to)i(cop)m(y)-8 +b(,)44 b(distribute)37 b(or)i(mo)s(dify)f(the)180 3904 +y(Program)31 b(sub)5 b(ject)32 b(to)g(these)f(terms)h(and)e +(conditions.)42 b(Y)-8 b(ou)32 b(ma)m(y)g(not)f(imp)s(ose)f(an)m(y)i +(further)e(restrictions)180 4029 y(on)g(the)h(recipien)m(ts')e +(exercise)i(of)g(the)f(righ)m(ts)g(gran)m(ted)h(herein.)49 +4175 y(8.)61 b(The)28 b(F)-8 b(ree)29 b(Soft)m(w)m(are)g(F)-8 +b(oundation)28 b(ma)m(y)h(publish)c(revised)i(and/or)h(new)g(v)m +(ersions)f(of)i(the)f(General)g(Public)180 4300 y(License)33 +b(from)f(time)h(to)g(time.)49 b(Suc)m(h)32 b(new)h(v)m(ersions)f(will)e +(b)s(e)j(similar)d(in)i(spirit)e(to)k(the)f(presen)m(t)g(v)m(ersion,) +180 4424 y(but)d(ma)m(y)h(di\013er)e(in)g(detail)g(to)i(address)f(new)g +(problems)e(or)j(concerns.)180 4571 y(Eac)m(h)44 b(v)m(ersion)f(is)f +(giv)m(en)h(a)h(distinguishing)39 b(v)m(ersion)k(n)m(um)m(b)s(er.)78 +b(If)43 b(the)g(Program)h(sp)s(eci\014es)e(a)h(v)m(ersion)180 +4695 y(n)m(um)m(b)s(er)e(of)i(the)f(license)g(whic)m(h)f(applies)f(to)j +(it)f(and)g(\\an)m(y)h(later)g(v)m(ersion",)i(y)m(ou)e(ha)m(v)m(e)g +(the)g(option)f(of)180 4820 y(follo)m(wing)31 b(the)i(terms)g(and)f +(conditions)f(either)h(of)h(that)g(v)m(ersion)f(or)h(of)f(an)m(y)h +(later)g(v)m(ersion)f(published)d(b)m(y)180 4944 y(the)c(F)-8 +b(ree)27 b(Soft)m(w)m(are)f(F)-8 b(oundation.)39 b(If)25 +b(the)g(Program)h(do)s(es)f(not)g(sp)s(ecify)f(a)i(v)m(ersion)f(n)m(um) +m(b)s(er)f(of)h(the)h(license,)180 5069 y(y)m(ou)31 b(ma)m(y)g(c)m(ho)s +(ose)g(an)m(y)g(v)m(ersion)f(ev)m(er)h(published)26 b(b)m(y)31 +b(the)f(F)-8 b(ree)32 b(Soft)m(w)m(are)f(F)-8 b(oundation.)49 +5215 y(9.)61 b(If)34 b(y)m(ou)h(wish)d(to)k(incorp)s(orate)e(parts)g +(of)g(the)h(Program)g(in)m(to)f(other)h(free)f(programs)g(whose)h +(distribution)180 5340 y(conditions)42 b(are)i(di\013eren)m(t,)j(write) +c(to)h(the)g(author)g(to)g(ask)g(for)f(p)s(ermission.)78 +b(F)-8 b(or)44 b(soft)m(w)m(are)h(whic)m(h)e(is)p eop +%%Page: 4 6 +4 5 bop 0 -116 a Fm(4)2965 b(User's)31 b(Guide)e(to)i +Fk(gperf)180 366 y Fm(cop)m(yrigh)m(ted)45 b(b)m(y)g(the)h(F)-8 +b(ree)46 b(Soft)m(w)m(are)g(F)-8 b(oundation,)49 b(write)44 +b(to)i(the)g(F)-8 b(ree)46 b(Soft)m(w)m(are)g(F)-8 b(oundation;)52 +b(w)m(e)180 491 y(sometimes)26 b(mak)m(e)h(exceptions)f(for)f(this.)38 +b(Our)25 b(decision)f(will)g(b)s(e)h(guided)f(b)m(y)i(the)g(t)m(w)m(o)h +(goals)f(of)g(preserving)180 616 y(the)i(free)h(status)f(of)g(all)f +(deriv)-5 b(ativ)m(es)28 b(of)g(our)g(free)g(soft)m(w)m(are)i(and)d(of) +i(promoting)e(the)i(sharing)d(and)i(reuse)g(of)180 740 +y(soft)m(w)m(are)k(generally)-8 b(.)180 1064 y Fi(NO)30 +b(W)-15 b(ARRANTY)4 1271 y Fm(10.)61 b(BECA)m(USE)41 +b(THE)f(PR)m(OGRAM)i(IS)e(LICENSED)g(FREE)h(OF)g(CHAR)m(GE,)g(THERE)f +(IS)h(NO)f(W)-10 b(AR-)180 1396 y(RANTY)22 b(F)m(OR)h(THE)f(PR)m +(OGRAM,)i(TO)d(THE)h(EXTENT)g(PERMITTED)g(BY)h(APPLICABLE)e(LA)-10 +b(W.)180 1520 y(EX)m(CEPT)46 b(WHEN)i(OTHER)-10 b(WISE)45 +b(ST)-8 b(A)g(TED)47 b(IN)g(WRITING)g(THE)f(COPYRIGHT)h(HOLDERS)180 +1645 y(AND/OR)21 b(OTHER)f(P)-8 b(AR)g(TIES)20 b(PR)m(O)m(VIDE)h(THE)f +(PR)m(OGRAM)h(\\AS)f(IS")g(WITHOUT)g(W)-10 b(ARRANTY)180 +1770 y(OF)28 b(ANY)h(KIND,)g(EITHER)e(EXPRESSED)h(OR)f(IMPLIED,)i +(INCLUDING,)g(BUT)f(NOT)g(LIMITED)180 1894 y(TO,)46 b(THE)g(IMPLIED)g +(W)-10 b(ARRANTIES)46 b(OF)h(MER)m(CHANT)-8 b(ABILITY)47 +b(AND)g(FITNESS)e(F)m(OR)i(A)180 2019 y(P)-8 b(AR)g(TICULAR)37 +b(PURPOSE.)f(THE)h(ENTIRE)f(RISK)g(AS)h(TO)f(THE)h(QUALITY)g(AND)h +(PERF)m(OR-)180 2143 y(MANCE)i(OF)f(THE)g(PR)m(OGRAM)h(IS)e(WITH)i +(YOU.)f(SHOULD)h(THE)f(PR)m(OGRAM)h(PR)m(O)m(VE)f(DE-)180 +2268 y(FECTIVE,)c(YOU)g(ASSUME)g(THE)g(COST)f(OF)i(ALL)f(NECESSAR)-8 +b(Y)34 b(SER)-10 b(VICING,)35 b(REP)-8 b(AIR)35 b(OR)180 +2392 y(CORRECTION.)4 2542 y(11.)61 b(IN)25 b(NO)g(EVENT)f(UNLESS)g +(REQUIRED)h(BY)g(APPLICABLE)g(LA)-10 b(W)25 b(OR)g(A)m(GREED)h(TO)e(IN) +h(WRIT-)180 2666 y(ING)i(WILL)g(ANY)g(COPYRIGHT)f(HOLDER,)h(OR)f(ANY)h +(OTHER)f(P)-8 b(AR)g(TY)27 b(WHO)g(MA)-8 b(Y)28 b(MODIFY)180 +2791 y(AND/OR)34 b(REDISTRIBUTE)d(THE)i(PR)m(OGRAM)g(AS)f(PERMITTED)g +(ABO)m(VE,)i(BE)f(LIABLE)g(TO)180 2915 y(YOU)26 b(F)m(OR)g(D)m(AMA)m +(GES,)h(INCLUDING)f(ANY)g(GENERAL,)g(SPECIAL,)e(INCIDENT)-8 +b(AL)26 b(OR)f(CON-)180 3040 y(SEQUENTIAL)36 b(D)m(AMA)m(GES)i(ARISING) +f(OUT)f(OF)h(THE)g(USE)f(OR)h(INABILITY)g(TO)f(USE)g(THE)180 +3164 y(PR)m(OGRAM)j(\(INCLUDING)g(BUT)f(NOT)g(LIMITED)g(TO)g(LOSS)e(OF) +j(D)m(A)-8 b(T)g(A)40 b(OR)d(D)m(A)-8 b(T)g(A)40 b(BEING)180 +3289 y(RENDERED)k(INA)m(CCURA)-8 b(TE)44 b(OR)f(LOSSES)f(SUST)-8 +b(AINED)43 b(BY)i(YOU)e(OR)h(THIRD)f(P)-8 b(AR)g(TIES)180 +3413 y(OR)28 b(A)h(F)-10 b(AILURE)29 b(OF)g(THE)f(PR)m(OGRAM)i(TO)e +(OPERA)-8 b(TE)28 b(WITH)h(ANY)g(OTHER)f(PR)m(OGRAMS\),)180 +3538 y(EVEN)38 b(IF)f(SUCH)h(HOLDER)f(OR)g(OTHER)g(P)-8 +b(AR)g(TY)38 b(HAS)g(BEEN)g(AD)m(VISED)g(OF)g(THE)f(POSSI-)180 +3662 y(BILITY)30 b(OF)g(SUCH)g(D)m(AMA)m(GES.)0 4111 +y Fi(END)h(OF)f(TERMS)f(AND)i(CONDITIONS)p eop +%%Page: 5 7 +5 6 bop 0 -116 a Fm(GNU)31 b(GENERAL)f(PUBLIC)h(LICENSE)2352 +b(5)0 366 y Fi(App)t(endix:)45 b(Ho)l(w)31 b(to)g(Apply)e(These)i(T)-11 +b(erms)30 b(to)h(Y)-11 b(our)29 b(New)i(Programs)125 +692 y Fm(If)g(y)m(ou)h(dev)m(elop)g(a)g(new)g(program,)g(and)f(y)m(ou)h +(w)m(an)m(t)h(it)f(to)g(b)s(e)g(of)g(the)g(greatest)h(p)s(ossible)d +(use)h(to)i(h)m(umanit)m(y)-8 b(,)0 816 y(the)28 b(b)s(est)g(w)m(a)m(y) +h(to)f(ac)m(hiev)m(e)i(this)d(is)g(to)h(mak)m(e)h(it)f(free)g(soft)m(w) +m(are)h(whic)m(h)e(ev)m(ery)m(one)j(can)e(redistribute)d(and)j(c)m +(hange)0 941 y(under)h(these)i(terms.)125 1266 y(T)-8 +b(o)28 b(do)h(so,)g(attac)m(h)h(the)f(follo)m(wing)e(notices)h(to)h +(the)g(program.)40 b(It)28 b(is)f(safest)i(to)h(attac)m(h)g(them)e(to)h +(the)g(start)g(of)0 1390 y(eac)m(h)34 b(source)g(\014le)e(to)i(most)f +(e\013ectiv)m(ely)h(con)m(v)m(ey)h(the)f(exclusion)d(of)j(w)m(arran)m +(t)m(y;)h(and)e(eac)m(h)h(\014le)f(should)e(ha)m(v)m(e)j(at)0 +1515 y(least)d(the)f(\\cop)m(yrigh)m(t")i(line)d(and)g(a)i(p)s(oin)m +(ter)e(to)j(where)d(the)i(full)d(notice)j(is)e(found.)240 +1819 y Fh(one)i(line)d(to)j(giv)m(e)g(the)g(program's)f(name)h(and)e(a) +i(brief)e(idea)h(of)g(what)h(it)f(do)s(es.)240 1923 y +Fk(Copyright)45 b(\(C\))i(19)p Fh(yy)103 b(name)30 b(of)h(author)240 +2130 y Fk(This)47 b(program)e(is)j(free)e(software;)g(you)g(can)h +(redistribute)e(it)i(and/or)f(modify)240 2234 y(it)h(under)g(the)f +(terms)h(of)g(the)g(GNU)g(General)f(Public)g(License)g(as)h(published)e +(by)240 2338 y(the)i(Free)g(Software)e(Foundation;)g(either)h(version)g +(1,)h(or)g(\(at)g(your)g(option\))240 2442 y(any)g(later)f(version.)240 +2649 y(This)h(program)e(is)j(distributed)c(in)k(the)e(hope)h(that)g(it) +g(will)g(be)g(useful,)240 2753 y(but)g(WITHOUT)f(ANY)h(WARRANTY;)e +(without)h(even)g(the)h(implied)f(warranty)g(of)240 2857 +y(MERCHANTABILITY)e(or)j(FITNESS)f(FOR)h(A)g(PARTICULAR)e(PURPOSE.)93 +b(See)47 b(the)240 2961 y(GNU)g(General)f(Public)g(License)g(for)h +(more)f(details.)240 3168 y(You)h(should)f(have)h(received)e(a)j(copy)e +(of)h(the)g(GNU)g(General)f(Public)g(License)240 3272 +y(along)g(with)h(this)g(program;)e(if)i(not,)g(write)f(to)i(the)e(Free) +h(Software)240 3376 y(Foundation,)e(Inc.,)h(59)h(Temple)f(Place)h(-)g +(Suite)g(330,)f(Boston,)g(MA)h(02111-1307,)e(USA.)125 +3701 y Fm(Also)30 b(add)f(information)g(on)h(ho)m(w)h(to)g(con)m(tact)i +(y)m(ou)d(b)m(y)g(electronic)h(and)f(pap)s(er)f(mail.)125 +4026 y(If)19 b(the)i(program)f(is)g(in)m(teractiv)m(e,)j(mak)m(e)e(it)f +(output)g(a)h(short)f(notice)h(lik)m(e)e(this)h(when)f(it)h(starts)h +(in)e(an)h(in)m(teractiv)m(e)0 4150 y(mo)s(de:)240 4455 +y Fk(Gnomovision)45 b(version)h(69,)g(Copyright)g(\(C\))h(19)p +Fh(yy)55 b(name)30 b(of)g(author)240 4558 y Fk(Gnomovision)45 +b(comes)h(with)h(ABSOLUTELY)e(NO)i(WARRANTY;)e(for)i(details)f(type)h +(`show)f(w'.)240 4662 y(This)h(is)g(free)f(software,)g(and)h(you)g(are) +f(welcome)g(to)h(redistribute)e(it)240 4766 y(under)h(certain)g +(conditions;)f(type)i(`show)f(c')h(for)g(details.)125 +5091 y Fm(The)36 b(h)m(yp)s(othetical)h(commands)g(`sho)m(w)g(w')h(and) +e(`sho)m(w)i(c')g(should)d(sho)m(w)i(the)h(appropriate)e(parts)h(of)h +(the)0 5215 y(General)21 b(Public)e(License.)37 b(Of)21 +b(course,)i(the)f(commands)f(y)m(ou)g(use)g(ma)m(y)h(b)s(e)e(called)h +(something)f(other)i(than)f(`sho)m(w)0 5340 y(w')30 b(and)g(`sho)m(w)g +(c';)i(they)e(could)g(ev)m(en)h(b)s(e)e(mouse-clic)m(ks)i(or)f(men)m(u) +g(items|whatev)m(er)h(suits)e(y)m(our)h(program.)p eop +%%Page: 6 8 +6 7 bop 0 -116 a Fm(6)2965 b(User's)31 b(Guide)e(to)i +Fk(gperf)125 366 y Fm(Y)-8 b(ou)28 b(should)f(also)h(get)h(y)m(our)f +(emplo)m(y)m(er)h(\(if)e(y)m(ou)i(w)m(ork)f(as)h(a)g(programmer\))f(or) +g(y)m(our)g(sc)m(ho)s(ol,)h(if)e(an)m(y)-8 b(,)30 b(to)f(sign)0 +491 y(a)i(\\cop)m(yrigh)m(t)g(disclaimer")d(for)j(the)f(program,)h(if)e +(necessary)-8 b(.)41 b(Here)31 b(a)g(sample;)f(alter)g(the)h(names:)240 +744 y Fk(Yoyodyne,)45 b(Inc.,)i(hereby)f(disclaims)f(all)i(copyright)e +(interest)h(in)h(the)240 848 y(program)f(`Gnomovision')e(\(a)j(program) +f(to)h(direct)f(compilers)g(to)h(make)f(passes)240 952 +y(at)h(assemblers\))e(written)h(by)h(James)f(Hacker.)240 +1159 y Fh(signature)30 b(of)g(T)m(y)h(Co)s(on)p Fk(,)47 +b(1)g(April)g(1989)240 1263 y(Ty)g(Coon,)g(President)e(of)i(Vice)125 +1537 y Fm(That's)30 b(all)f(there)i(is)e(to)i(it!)p eop +%%Page: 7 9 +7 8 bop 0 -116 a Fm(Con)m(tributors)29 b(to)i(GNU)g Fk(gperf)e +Fm(Utilit)m(y)2437 b(7)0 366 y Fj(Con)l(tributors)28 +b(to)h(GNU)i Fg(gperf)e Fj(Utilit)l(y)75 740 y Fl(\017)60 +b Fm(The)36 b(GNU)h Fk(gperf)e Fm(p)s(erfect)h(hash)f(function)g +(generator)j(utilit)m(y)c(w)m(as)j(originally)d(written)h(in)g(GNU)i(C) +p Fk(++)180 865 y Fm(b)m(y)h(Douglas)h(C.)f(Sc)m(hmidt.)62 +b(It)39 b(is)e(no)m(w)h(also)g(a)m(v)-5 b(ailable)38 +b(in)f(a)h(highly-p)s(ortable)e(\\old-st)m(yle")i(C)g(v)m(ersion.)180 +989 y(The)g(general)h(idea)g(for)f(the)h(p)s(erfect)g(hash)f(function)g +(generator)i(w)m(as)f(inspired)d(b)m(y)i(Keith)g(Bostic's)i(al-)180 +1114 y(gorithm)e(written)g(in)g(C,)g(and)h(distributed)c(to)40 +b(net.sources)f(around)f(1984.)68 b(The)39 b(curren)m(t)f(program)h(is) +180 1238 y(a)34 b(hea)m(vily)f(mo)s(di\014ed,)f(enhanced,)i(and)f +(extended)g(implemen)m(tation)f(of)i(Keith's)f(basic)g(idea,)h(created) +g(at)180 1363 y(the)41 b(Univ)m(ersit)m(y)g(of)g(California,)h(Irvine.) +72 b(Bugs,)45 b(patc)m(hes,)g(and)c(suggestions)g(should)e(b)s(e)i(rep) +s(orted)f(to)180 1487 y Fk()24 +b Fm(and)30 b Fk()p Fm(.)75 1637 +y Fl(\017)60 b Fm(Sp)s(ecial)24 b(thanks)i(is)f(extended)i(to)g(Mic)m +(hael)f(Tiemann)e(and)i(Doug)h(Lea,)h(for)e(pro)m(viding)e(a)j(useful)d +(compiler,)180 1761 y(and)30 b(for)g(giving)f(me)i(a)f(forum)g(to)h +(exhibit)d(m)m(y)j(creation.)180 1911 y(In)23 b(addition,)h(Adam)f(de)h +(Bo)s(or)g(and)f(Nels)h(Olson)e(pro)m(vided)g(man)m(y)i(tips)f(and)g +(insigh)m(ts)f(that)j(greatly)f(help)s(ed)180 2035 y(impro)m(v)m(e)30 +b(the)h(qualit)m(y)e(and)h(functionalit)m(y)f(of)h Fk(gperf)p +Fm(.)p eop +%%Page: 8 10 +8 9 bop 0 -116 a Fm(8)2965 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Page: 9 11 +9 10 bop 0 -116 a Fm(Chapter)30 b(1:)41 b(In)m(tro)s(duction)2891 +b(9)0 366 y Fj(1)80 b(In)l(tro)t(duction)125 740 y Fk(gperf)36 +b Fm(is)g(a)j(p)s(erfect)e(hash)g(function)f(generator)j(written)e(in)f +(C)p Fk(++)p Fm(.)62 b(It)38 b(transforms)f(an)g Fh(n)g +Fm(elemen)m(t)h(user-)0 865 y(sp)s(eci\014ed)28 b(k)m(eyw)m(ord)h(set)h +Fh(W)41 b Fm(in)m(to)29 b(a)h(p)s(erfect)f(hash)g(function)f +Fh(F)p Fm(.)h Fh(F)36 b Fm(uniquely)27 b(maps)i(k)m(eyw)m(ords)g(in)f +Fh(W)41 b Fm(on)m(to)31 b(the)0 989 y(range)i(0..)p Fh(k)p +Fm(,)h(where)d Fh(k)i Fk(>)p Fh(=)e(n)p Fm(.)46 b(If)32 +b Fh(k)g(=)g(n)g Fm(then)g Fh(F)39 b Fm(is)31 b(a)i Fh(minimal)g +Fm(p)s(erfect)f(hash)g(function.)45 b Fk(gperf)31 b Fm(generates)j(a)0 +1114 y(0..)p Fh(k)41 b Fm(elemen)m(t)35 b(static)g(lo)s(okup)e(table)i +(and)f(a)h(pair)e(of)i(C)f(functions.)52 b(These)34 b(functions)f +(determine)h(whether)g(a)0 1238 y(giv)m(en)c(c)m(haracter)i(string)e +Fh(s)k Fm(o)s(ccurs)c(in)f Fh(W)p Fm(,)i(using)e(at)i(most)f(one)h +(prob)s(e)e(in)m(to)i(the)f(lo)s(okup)f(table.)125 1512 +y Fk(gperf)i Fm(curren)m(tly)i(generates)h(the)g(reserv)m(ed)f(k)m(eyw) +m(ord)h(recognizer)f(for)g(lexical)g(analyzers)g(in)f(sev)m(eral)h +(pro-)0 1637 y(duction)28 b(and)g(researc)m(h)i(compilers)e(and)g +(language)i(pro)s(cessing)d(to)s(ols,)j(including)25 +b(GNU)30 b(C,)f(GNU)h(C)p Fk(++)p Fm(,)e(GNU)0 1761 y(P)m(ascal,)39 +b(GNU)e(Mo)s(dula)f(3,)j(and)d(GNU)h(inden)m(t.)58 b(Complete)37 +b(C)p Fk(++)e Fm(source)i(co)s(de)g(for)f Fk(gperf)g +Fm(is)f(a)m(v)-5 b(ailable)36 b(via)0 1886 y(anon)m(ymous)d(ftp)h(from) +f Fk(ics.uci.edu)d Fm(and)j Fk(ftp.santafe.edu)p Fm(.)46 +b Fk(gperf)33 b Fm(w)m(as)g(also)h(distributed)d(along)i(with)0 +2010 y(the)h(GNU)g(libg)p Fk(++)d Fm(library)h(for)h(sev)m(eral)h(y)m +(ears.)51 b(A)34 b(highly)d(p)s(ortable,)j(functionally)d(equiv)-5 +b(alen)m(t)33 b(K&R)g(C)g(v)m(er-)0 2135 y(sion)39 b(of)h +Fk(gperf)e Fm(is)h(arc)m(hiv)m(ed)h(in)f(comp.sources.unix,)i(v)m +(olume)f(20.)70 b(Finally)-8 b(,)41 b(a)f(pap)s(er)f(describing)e +Fk(gperf)p Fm('s)0 2259 y(design)f(and)g(implemen)m(tation)g(in)f +(greater)j(detail)e(is)g(a)m(v)-5 b(ailable)36 b(in)g(the)h(Second)f +(USENIX)h(C)p Fk(++)f Fm(Conference)0 2384 y(pro)s(ceedings.)p +eop +%%Page: 10 12 +10 11 bop 0 -116 a Fm(10)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Page: 11 13 +11 12 bop 0 -116 a Fm(Chapter)30 b(2:)41 b(Static)31 +b(searc)m(h)g(structures)e(and)h(GNU)h Fk(gperf)1725 +b Fm(11)0 366 y Fj(2)80 b(Static)31 b(searc)l(h)e(structures)e(and)k +(GNU)f Fg(gperf)125 768 y Fm(A)j Fh(static)h(searc)m(h)f(structure)38 +b Fm(is)32 b(an)i(Abstract)f(Data)i(T)m(yp)s(e)e(with)f(certain)h +(fundamen)m(tal)f(op)s(erations,)h(e.g.,)0 892 y Fh(initialize)p +Fm(,)c Fh(insert)p Fm(,)h(and)g Fh(retriev)m(e)p Fm(.)43 +b(Conceptually)-8 b(,)30 b(all)g(insertions)f(o)s(ccur)i(b)s(efore)f +(an)m(y)i(retriev)-5 b(als.)41 b(In)30 b(practice,)0 +1017 y Fk(gperf)44 b Fm(generates)i(a)f Fk(static)f Fm(arra)m(y)h(con)m +(taining)g(searc)m(h)g(set)h(k)m(eyw)m(ords)f(and)g(an)m(y)g(asso)s +(ciated)g(attributes)0 1142 y(sp)s(eci\014ed)38 b(b)m(y)i(the)f(user.) +68 b(Th)m(us,)42 b(there)d(is)g(essen)m(tially)g(no)g(execution-time)h +(cost)h(for)f(the)f(insertions.)67 b(It)40 b(is)0 1266 +y(a)e(useful)d(data)j(structure)f(for)g(represen)m(ting)f +Fh(static)i(searc)m(h)g(sets)p Fm(.)62 b(Static)37 b(searc)m(h)h(sets)g +(o)s(ccur)f(frequen)m(tly)f(in)0 1391 y(soft)m(w)m(are)28 +b(system)g(applications.)37 b(T)m(ypical)26 b(static)i(searc)m(h)f +(sets)h(include)c(compiler)i(reserv)m(ed)h(w)m(ords,)g(assem)m(bler)0 +1515 y(instruction)22 b(op)s(co)s(des,)j(and)e(built-in)e(shell)h(in)m +(terpreter)h(commands.)38 b(Searc)m(h)24 b(set)h(mem)m(b)s(ers,)f +(called)f Fh(k)m(eyw)m(ords)p Fm(,)0 1640 y(are)f(inserted)e(in)m(to)h +(the)g(structure)g(only)g(once,)j(usually)19 b(during)g(program)i +(initialization,)f(and)h(are)g(not)h(generally)0 1764 +y(mo)s(di\014ed)28 b(at)j(run-time.)125 2044 y(Numerous)e(static)i +(searc)m(h)g(structure)f(implemen)m(tations)f(exist,)i(e.g.,)h(arra)m +(ys,)f(link)m(ed)d(lists,)i(binary)e(searc)m(h)0 2168 +y(trees,)45 b(digital)c(searc)m(h)h(tries,)i(and)e(hash)f(tables.)74 +b(Di\013eren)m(t)43 b(approac)m(hes)f(o\013er)g(trade-o\013s)h(b)s(et)m +(w)m(een)f(space)0 2293 y(utilization)36 b(and)h(searc)m(h)i(time)e +(e\016ciency)-8 b(.)64 b(F)-8 b(or)39 b(example,)h(an)e +Fh(n)f Fm(elemen)m(t)h(sorted)g(arra)m(y)h(is)e(space)h(e\016cien)m(t,) +0 2417 y(though)24 b(the)g(a)m(v)m(erage-case)k(time)c(complexit)m(y)g +(for)g(retriev)-5 b(al)24 b(op)s(erations)f(using)g(binary)f(searc)m(h) +j(is)e(prop)s(ortional)0 2542 y(to)34 b(log)f Fh(n)p +Fm(.)48 b(Con)m(v)m(ersely)-8 b(,)34 b(hash)f(table)g(implemen)m +(tations)e(often)j(lo)s(cate)f(a)h(table)f(en)m(try)g(in)f(constan)m(t) +i(time,)g(but)0 2666 y(t)m(ypically)29 b(imp)s(ose)g(additional)g +(memory)h(o)m(v)m(erhead)h(and)f(exhibit)f(p)s(o)s(or)g(w)m(orst)i +(case)g(p)s(erformance.)125 2946 y Fh(Minimal)23 b(p)s(erfect)i(hash)g +(functions)i Fm(pro)m(vide)e(an)g(optimal)g(solution)f(for)h(a)h +(particular)d(class)j(of)f(static)h(searc)m(h)0 3071 +y(sets.)41 b(A)31 b(minimal)c(p)s(erfect)j(hash)g(function)f(is)h +(de\014ned)f(b)m(y)h(t)m(w)m(o)i(prop)s(erties:)75 3350 +y Fl(\017)60 b Fm(It)25 b(allo)m(ws)e(k)m(eyw)m(ord)i(recognition)f(in) +g(a)g(static)i(searc)m(h)f(set)g(using)e(at)i(most)g +Fh(one)30 b Fm(prob)s(e)23 b(in)m(to)h(the)h(hash)f(table.)180 +3475 y(This)29 b(represen)m(ts)h(the)g(\\p)s(erfect")i(prop)s(ert)m(y) +-8 b(.)75 3630 y Fl(\017)60 b Fm(The)31 b(actual)h(memory)f(allo)s +(cated)g(to)h(store)g(the)g(k)m(eyw)m(ords)g(is)e(precisely)g(large)i +(enough)f(for)g(the)g(k)m(eyw)m(ord)180 3754 y(set,)g(and)f +Fh(no)g(larger)p Fm(.)41 b(This)28 b(is)i(the)g(\\minimal")f(prop)s +(ert)m(y)-8 b(.)125 4064 y(F)g(or)22 b(most)g(applications)e(it)i(is)e +(far)i(easier)g(to)g(generate)h Fh(p)s(erfect)h Fm(hash)d(functions)g +(than)g Fh(minimal)e(p)s(erfect)24 b Fm(hash)0 4189 y(functions.)56 +b(Moreo)m(v)m(er,)40 b(non-minimal)33 b(p)s(erfect)j(hash)f(functions)f +(frequen)m(tly)h(execute)j(faster)e(than)g(minimal)0 +4313 y(ones)43 b(in)e(practice.)77 b(This)41 b(phenomena)h(o)s(ccurs)g +(since)g(searc)m(hing)g(a)h(sparse)f(k)m(eyw)m(ord)h(table)g(increases) +f(the)0 4438 y(probabilit)m(y)19 b(of)i(lo)s(cating)g(a)h(\\n)m(ull")e +(en)m(try)-8 b(,)25 b(thereb)m(y)c(reducing)f(string)g(comparisons.)37 +b Fk(gperf)p Fm('s)20 b(default)h(b)s(eha)m(vior)0 4562 +y(generates)38 b Fh(near-minimal)g Fm(p)s(erfect)f(hash)f(functions)f +(for)i(k)m(eyw)m(ord)g(sets.)60 b(Ho)m(w)m(ev)m(er,)41 +b Fk(gperf)35 b Fm(pro)m(vides)h(man)m(y)0 4687 y(options)30 +b(that)h(p)s(ermit)d(user)i(con)m(trol)h(o)m(v)m(er)h(the)e(degree)h +(of)g(minimalit)m(y)c(and)j(p)s(erfection.)125 4966 y(Static)23 +b(searc)m(h)g(sets)h(often)f(exhibit)e(relativ)m(e)i(stabilit)m(y)f(o)m +(v)m(er)i(time.)38 b(F)-8 b(or)24 b(example,)g(Ada's)f(63)h(reserv)m +(ed)f(w)m(ords)0 5091 y(ha)m(v)m(e)35 b(remained)d(constan)m(t)j(for)e +(nearly)f(a)i(decade.)51 b(It)33 b(is)g(therefore)g(frequen)m(tly)g(w)m +(orth)m(while)f(to)i(exp)s(end)e(con-)0 5215 y(certed)23 +b(e\013ort)g(building)18 b(an)k(optimal)f(searc)m(h)h(structure)g +Fh(once)p Fm(,)j(if)c(it)g(subsequen)m(tly)g(receiv)m(es)i(hea)m(vy)f +(use)g(m)m(ultiple)0 5340 y(times.)55 b Fk(gperf)34 b +Fm(remo)m(v)m(es)i(the)g(drudgery)d(asso)s(ciated)j(with)e +(constructing)h(time-)g(and)g(space-e\016cien)m(t)h(searc)m(h)p +eop +%%Page: 12 14 +12 13 bop 0 -116 a Fm(12)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)0 366 y Fm(structures)37 b(b)m(y)h(hand.)61 +b(It)38 b(has)f(pro)m(v)m(en)h(a)g(useful)e(and)h(practical)g(to)s(ol)h +(for)f(serious)g(programming)f(pro)5 b(jects.)0 491 y(Output)27 +b(from)i Fk(gperf)e Fm(is)g(curren)m(tly)h(used)g(in)f(sev)m(eral)i +(pro)s(duction)d(and)i(researc)m(h)i(compilers,)d(including)e(GNU)0 +616 y(C,)39 b(GNU)h(C)p Fk(++)p Fm(,)h(GNU)f(P)m(ascal,)i(and)d(GNU)h +(Mo)s(dula)e(3.)68 b(The)38 b(latter)i(t)m(w)m(o)g(compilers)e(are)i +(not)f(y)m(et)i(part)e(of)0 740 y(the)28 b(o\016cial)g(GNU)g +(distribution.)36 b(Eac)m(h)29 b(compiler)d(utilizes)g +Fk(gperf)h Fm(to)i(automatically)e(generate)j(static)e(searc)m(h)0 +865 y(structures)i(that)h(e\016cien)m(tly)f(iden)m(tify)f(their)g(resp) +s(ectiv)m(e)i(reserv)m(ed)f(k)m(eyw)m(ords.)p eop +%%Page: 13 15 +13 14 bop 0 -116 a Fm(Chapter)30 b(3:)41 b(High-Lev)m(el)30 +b(Description)g(of)g(GNU)h Fk(gperf)1820 b Fm(13)0 366 +y Fj(3)80 b(High-Lev)l(el)31 b(Description)e(of)h(GNU)h +Fg(gperf)125 849 y Fm(The)k(p)s(erfect)i(hash)e(function)h(generator)h +Fk(gperf)e Fm(reads)h(a)h(set)g(of)g(\\k)m(eyw)m(ords")g(from)f(a)h +Fh(k)m(ey\014le)42 b Fm(\(or)36 b(from)0 974 y(the)g(standard)g(input)e +(b)m(y)i(default\).)57 b(It)36 b(attempts)h(to)g(deriv)m(e)f(a)g(p)s +(erfect)g(hashing)f(function)g(that)h(recognizes)0 1099 +y(a)g(mem)m(b)s(er)f(of)h(the)g Fh(static)h(k)m(eyw)m(ord)f(set)i +Fm(with)d(at)h(most)h(a)f(single)e(prob)s(e)h(in)m(to)h(the)g(lo)s +(okup)e(table.)57 b(If)35 b Fk(gperf)0 1223 y Fm(succeeds)g(in)e +(generating)h(suc)m(h)h(a)f(function)f(it)h(pro)s(duces)f(a)i(pair)e +(of)i(C)f(source)g(co)s(de)h(routines)e(that)i(p)s(erform)0 +1348 y(hashing)h(and)g(table)h(lo)s(okup)f(recognition.)61 +b(All)36 b(generated)i(C)f(co)s(de)g(is)g(directed)f(to)i(the)g +(standard)e(output.)0 1472 y(Command-line)24 b(options)i(describ)s(ed)e +(b)s(elo)m(w)h(allo)m(w)h(y)m(ou)h(to)g(mo)s(dify)d(the)j(input)d(and)i +(output)f(format)i(to)g Fk(gperf)p Fm(.)125 1768 y(By)h(default,)g +Fk(gperf)f Fm(attempts)j(to)f(pro)s(duce)e(time-e\016cien)m(t)i(co)s +(de,)g(with)e(less)g(emphasis)g(on)i(e\016cien)m(t)f(space)0 +1892 y(utilization.)38 b(Ho)m(w)m(ev)m(er,)32 b(sev)m(eral)e(options)e +(exist)h(that)h(p)s(ermit)d(trading-o\013)i(execution)h(time)f(for)g +(storage)h(space)0 2017 y(and)23 b(vice)h(v)m(ersa.)39 +b(In)23 b(particular,)g(expanding)g(the)g(generated)i(table)f(size)f +(pro)s(duces)g(a)h(sparse)f(searc)m(h)h(structure,)0 +2142 y(generally)g(yielding)e(faster)k(searc)m(hes.)39 +b(Con)m(v)m(ersely)-8 b(,)27 b(y)m(ou)e(can)g(direct)f +Fk(gperf)g Fm(to)h(utilize)e(a)j(C)e Fk(switch)f Fm(statemen)m(t)0 +2266 y(sc)m(heme)28 b(that)f(minimizes)d(data)k(space)f(storage)i +(size.)39 b(F)-8 b(urthermore,)28 b(using)d(a)i(C)g Fk(switch)e +Fm(ma)m(y)i(actually)g(sp)s(eed)0 2391 y(up)i(the)i(k)m(eyw)m(ord)g +(retriev)-5 b(al)29 b(time)h(somewhat.)41 b(Actual)31 +b(results)e(dep)s(end)g(on)h(y)m(our)g(C)g(compiler,)f(of)i(course.)125 +2686 y(In)c(general,)h Fk(gperf)f Fm(assigns)g(v)-5 b(alues)27 +b(to)h(the)g(c)m(haracters)i(it)d(is)g(using)f(for)i(hashing)e(un)m +(til)g(some)i(set)h(of)f(v)-5 b(alues)0 2811 y(giv)m(es)31 +b(eac)m(h)g(k)m(eyw)m(ord)g(a)f(unique)f(v)-5 b(alue.)40 +b(A)30 b(helpful)d(heuristic)i(is)g(that)i(the)f(larger)g(the)h(hash)e +(v)-5 b(alue)30 b(range,)h(the)0 2936 y(easier)i(it)g(is)f(for)g +Fk(gperf)g Fm(to)i(\014nd)d(and)i(generate)h(a)g(p)s(erfect)f(hash)f +(function.)47 b(Exp)s(erimen)m(tation)32 b(is)g(the)h(k)m(ey)h(to)0 +3060 y(getting)d(the)g(most)f(from)g Fk(gperf)p Fm(.)0 +3705 y Fi(3.1)68 b(Input)30 b(F)-11 b(ormat)31 b(to)f +Ff(gperf)125 4001 y Fm(Y)-8 b(ou)28 b(can)g(con)m(trol)g(the)g(input)d +(k)m(ey\014le)j(format)g(b)m(y)f(v)-5 b(arying)27 b(certain)h +(command-line)e(argumen)m(ts,)j(in)d(partic-)0 4126 y(ular)h(the)i(`)p +Fk(-t)p Fm(')g(option.)40 b(The)28 b(input's)f(app)s(earance)i(is)e +(similar)g(to)i(GNU)g(utilities)e Fk(flex)g Fm(and)h +Fk(bison)g Fm(\(or)h(UNIX)0 4250 y(utilities)f Fk(lex)h +Fm(and)h Fk(yacc)p Fm(\).)40 b(Here's)31 b(an)f(outline)f(of)i(the)f +(general)h(format:)240 4525 y Fk(declarations)240 4629 +y(\045\045)240 4733 y(keywords)240 4837 y(\045\045)240 +4940 y(functions)125 5215 y Fh(Unlik)m(e)f Fk(flex)25 +b Fm(or)h Fk(bison)p Fm(,)g(all)f(sections)h(of)g Fk(gperf)p +Fm('s)f(input)f(are)j(optional.)38 b(The)26 b(follo)m(wing)e(sections)j +(describ)s(e)0 5340 y(the)k(input)d(format)j(for)f(eac)m(h)h(section.)p +eop +%%Page: 14 16 +14 15 bop 0 -116 a Fm(14)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)0 366 y Fe(3.1.1)63 b Fd(struct)31 b Fe(Declarations)f(and)g +(C)g(Co)s(de)h(Inclusion)125 876 y Fm(The)f(k)m(eyw)m(ord)i(input)d +(\014le)h(optionally)g(con)m(tains)h(a)h(section)f(for)g(including)c +(arbitrary)j(C)h(declarations)g(and)0 1000 y(de\014nitions,)25 +b(as)i(w)m(ell)f(as)h(pro)m(visions)e(for)h(pro)m(viding)f(a)i +(user-supplied)c Fk(struct)p Fm(.)38 b(If)26 b(the)h(`)p +Fk(-t)p Fm(')g(option)f Fh(is)k Fm(enabled,)0 1125 y(y)m(ou)39 +b Fh(m)m(ust)h Fm(pro)m(vide)d(a)i(C)f Fk(struct)e Fm(as)j(the)f(last)g +(comp)s(onen)m(t)h(in)e(the)h(declaration)g(section)h(from)f(the)g(k)m +(ey\014le)0 1249 y(\014le.)50 b(The)34 b(\014rst)f(\014eld)f(in)h(this) +g(struct)g(m)m(ust)h(b)s(e)f(a)i Fk(char)29 b(*)k Fm(iden)m(ti\014er)f +(called)h(`)p Fk(name)p Fm(',)i(although)e(it)g(is)g(p)s(ossible)0 +1374 y(to)e(mo)s(dify)e(this)g(\014eld's)g(name)h(with)g(the)g(`)p +Fk(-K)p Fm(')g(option)g(describ)s(ed)e(b)s(elo)m(w.)125 +1883 y(Here)i(is)g(simple)e(example,)i(using)f(mon)m(ths)i(of)f(the)h +(y)m(ear)g(and)f(their)f(attributes)h(as)h(input:)240 +2371 y Fk(struct)46 b(months)g({)i(char)e(*name;)g(int)h(number;)f(int) +h(days;)f(int)h(leap_days;)e(};)240 2475 y(\045\045)240 +2578 y(january,)141 b(1,)47 b(31,)g(31)240 2682 y(february,)93 +b(2,)47 b(28,)g(29)240 2786 y(march,)237 b(3,)47 b(31,)g(31)240 +2890 y(april,)237 b(4,)47 b(30,)g(30)240 2994 y(may,)333 +b(5,)47 b(31,)g(31)240 3097 y(june,)285 b(6,)47 b(30,)g(30)240 +3201 y(july,)285 b(7,)47 b(31,)g(31)240 3305 y(august,)189 +b(8,)47 b(31,)g(31)240 3409 y(september,)e(9,)i(30,)g(30)240 +3512 y(october,)93 b(10,)47 b(31,)g(31)240 3616 y(november,)e(11,)i +(30,)g(30)240 3720 y(december,)e(12,)i(31,)g(31)125 4208 +y Fm(Separating)41 b(the)i Fk(struct)d Fm(declaration)i(from)g(the)g +(list)f(of)i(k)m(ey)g(w)m(ords)f(and)f(other)i(\014elds)d(are)j(a)g +(pair)e(of)0 4333 y(consecutiv)m(e)c(p)s(ercen)m(t)f(signs,)h +Fk(\045\045)p Fm(,)g(app)s(earing)e(left)h(justi\014ed)e(in)h(the)h +(\014rst)g(column,)h(as)f(in)f(the)h(UNIX)h(utilit)m(y)0 +4457 y Fk(lex)p Fm(.)125 4966 y(Using)21 b(a)h(syn)m(tax)h(similar)c +(to)k(GNU)g(utilities)c Fk(flex)i Fm(and)h Fk(bison)p +Fm(,)g(it)g(is)f(p)s(ossible)f(to)i(directly)f(include)f(C)i(source)0 +5091 y(text)31 b(and)e(commen)m(ts)h(v)m(erbatim)g(in)m(to)f(the)h +(generated)h(output)e(\014le.)40 b(This)27 b(is)i(accomplished)g(b)m(y) +g(enclosing)g(the)0 5215 y(region)23 b(inside)d(left-justi\014ed)h +(surrounding)f Fk(\045{)p Fm(,)k Fk(\045})f Fm(pairs.)37 +b(Here)23 b(is)f(an)h(input)e(fragmen)m(t)j(based)e(on)h(the)g +(previous)0 5340 y(example)30 b(that)h(illustrates)d(this)i(feature:)p +eop +%%Page: 15 17 +15 16 bop 0 -116 a Fm(Chapter)30 b(3:)41 b(High-Lev)m(el)30 +b(Description)g(of)g(GNU)h Fk(gperf)1820 b Fm(15)240 +366 y Fk(\045{)240 470 y(#include)46 b()240 +574 y(/*)h(This)g(section)f(of)h(code)f(is)i(inserted)d(directly)h +(into)g(the)h(output.)f(*/)240 678 y(int)h(return_month_days)c +(\(struct)j(months)g(*months,)f(int)i(is_leap_year\);)240 +782 y(\045})240 885 y(struct)f(months)g({)i(char)e(*name;)g(int)h +(number;)f(int)h(days;)f(int)h(leap_days;)e(};)240 989 +y(\045\045)240 1093 y(january,)141 b(1,)47 b(31,)g(31)240 +1197 y(february,)93 b(2,)47 b(28,)g(29)240 1300 y(march,)237 +b(3,)47 b(31,)g(31)240 1404 y(...)125 1659 y Fm(It)25 +b(is)g(p)s(ossible)e(to)j(omit)f(the)h(declaration)f(section)h(en)m +(tirely)-8 b(.)38 b(In)25 b(this)f(case)j(the)f(k)m(ey\014le)f(b)s +(egins)f(directly)g(with)0 1784 y(the)31 b(\014rst)e(k)m(eyw)m(ord)i +(line,)e(e.g.:)240 2039 y Fk(january,)141 b(1,)47 b(31,)g(31)240 +2142 y(february,)93 b(2,)47 b(28,)g(29)240 2246 y(march,)237 +b(3,)47 b(31,)g(31)240 2350 y(april,)237 b(4,)47 b(30,)g(30)240 +2454 y(...)0 2876 y Fe(3.1.2)63 b(F)-10 b(ormat)29 b(for)h(Keyw)m(ord)g +(En)m(tries)125 3152 y Fm(The)g(second)h(k)m(ey\014le)h(format)f +(section)g(con)m(tains)h(lines)d(of)j(k)m(eyw)m(ords)f(and)g(an)m(y)g +(asso)s(ciated)h(attributes)f(y)m(ou)0 3276 y(migh)m(t)i(supply)-8 +b(.)47 b(A)33 b(line)f(b)s(eginning)e(with)i(`)p Fk(#)p +Fm(')h(in)f(the)h(\014rst)g(column)f(is)g(considered)g(a)i(commen)m(t.) +50 b(Ev)m(erything)0 3401 y(follo)m(wing)29 b(the)h(`)p +Fk(#)p Fm(')h(is)e(ignored,)h(up)f(to)j(and)d(including)e(the)k(follo)m +(wing)e(newline.)125 3677 y(The)h(\014rst)g(\014eld)f(of)i(eac)m(h)h +(non-commen)m(t)g(line)d(is)h(alw)m(a)m(ys)h(the)g(k)m(ey)h(itself.)41 +b(It)31 b(should)e(b)s(e)h(giv)m(en)h(as)g(a)g(simple)0 +3801 y(name,)g(i.e.,)f(without)g(surrounding)c(string)k(quotation)g +(marks,)g(and)g(b)s(e)g(left-justi\014ed)e(\015ush)h(against)h(the)h +(\014rst)0 3926 y(column.)51 b(In)34 b(this)f(con)m(text,)k(a)e +(\\\014eld")f(is)f(considered)g(to)i(extend)f(up)g(to,)i(but)d(not)i +(include,)e(the)i(\014rst)e(blank,)0 4050 y(comma,)e(or)g(newline.)38 +b(Here)31 b(is)f(a)g(simple)f(example)h(tak)m(en)h(from)f(a)h(partial)e +(list)g(of)i(C)f(reserv)m(ed)g(w)m(ords:)240 4305 y Fk(#)47 +b(These)g(are)g(a)g(few)g(C)h(reserved)d(words,)h(see)h(the)g(c.gperf)f +(file)240 4409 y(#)h(for)g(a)h(complete)d(list)i(of)g(ANSI)g(C)g +(reserved)f(words.)240 4513 y(unsigned)240 4616 y(sizeof)240 +4720 y(switch)240 4824 y(signed)240 4928 y(if)240 5032 +y(default)240 5135 y(for)240 5239 y(while)240 5343 y(return)p +eop +%%Page: 16 18 +16 17 bop 0 -116 a Fm(16)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)125 366 y Fm(Note)j(that)g(unlik)m(e)e Fk(flex)h +Fm(or)g Fk(bison)f Fm(the)i(\014rst)f Fk(\045\045)g Fm(mark)m(er)g(ma)m +(y)h(b)s(e)f(elided)f(if)g(the)i(declaration)f(section)h(is)0 +491 y(empt)m(y)-8 b(.)125 772 y(Additional)39 b(\014elds)h(ma)m(y)i +(optionally)e(follo)m(w)g(the)i(leading)e(k)m(eyw)m(ord.)75 +b(Fields)40 b(should)f(b)s(e)i(separated)h(b)m(y)0 896 +y(commas,)h(and)c(terminate)h(at)h(the)f(end)f(of)h(line.)68 +b(What)40 b(these)h(\014elds)d(mean)i(is)f(en)m(tirely)g(up)g(to)i(y)m +(ou;)k(they)0 1021 y(are)36 b(used)e(to)j(initialize)32 +b(the)k(elemen)m(ts)g(of)f(the)h(user-de\014ned)e Fk(struct)g +Fm(pro)m(vided)g(b)m(y)h(y)m(ou)h(in)e(the)h(declaration)0 +1145 y(section.)61 b(If)36 b(the)i(`)p Fk(-t)p Fm(')f(option)f(is)g +Fh(not)j Fm(enabled)d(these)i(\014elds)d(are)j(simply)c(ignored.)60 +b(All)36 b(previous)f(examples)0 1270 y(except)c(the)g(last)f(one)h +(con)m(tain)g(k)m(eyw)m(ord)f(attributes.)0 1746 y Fe(3.1.3)63 +b(Including)30 b(Additional)h(C)f(F)-10 b(unctions)125 +2027 y Fm(The)30 b(optional)h(third)e(section)i(also)h(corresp)s(onds)e +(closely)g(with)g(con)m(v)m(en)m(tions)j(found)c(in)h +Fk(flex)g Fm(and)h Fk(bison)p Fm(.)0 2151 y(All)23 b(text)i(in)f(this)f +(section,)j(starting)e(at)h(the)g(\014nal)e Fk(\045\045)h +Fm(and)f(extending)h(to)h(the)g(end)f(of)g(the)h(input)d(\014le,)j(is)f +(included)0 2276 y(v)m(erbatim)k(in)m(to)h(the)g(generated)h(output)e +(\014le.)40 b(Naturally)-8 b(,)28 b(it)h(is)e(y)m(our)i(resp)s +(onsibilit)m(y)c(to)k(ensure)f(that)i(the)f(co)s(de)0 +2400 y(con)m(tained)i(in)e(this)g(section)h(is)g(v)-5 +b(alid)29 b(C.)0 2909 y Fi(3.2)68 b(Output)30 b(F)-11 +b(ormat)31 b(for)f(Generated)i(C)e(Co)t(de)g(with)h Ff(gperf)125 +3190 y Fm(Sev)m(eral)40 b(options)h(con)m(trol)g(ho)m(w)g(the)g +(generated)h(C)f(co)s(de)g(app)s(ears)f(on)h(the)g(standard)f(output.) +72 b(Tw)m(o)41 b(C)0 3315 y(function)d(are)i(generated.)70 +b(They)39 b(are)h(called)e Fk(hash)h Fm(and)g Fk(in_word_set)p +Fm(,)g(although)g(y)m(ou)h(ma)m(y)g(mo)s(dify)e(the)0 +3439 y(name)k(for)g Fk(in_word_set)d Fm(with)i(a)h(command-line)f +(option.)75 b(Both)43 b(functions)e(require)g(t)m(w)m(o)i(argumen)m +(ts,)j(a)0 3564 y(string,)g Fk(char)29 b(*)43 b Fh(str)p +Fm(,)j(and)c(a)i(length)f(parameter,)k Fk(int)42 b Fh(len)p +Fm(.)78 b(Their)41 b(default)i(function)f(protot)m(yp)s(es)h(are)h(as)0 +3688 y(follo)m(ws:)240 3948 y Fk(static)i(int)h(hash)g(\(char)f(*str,)g +(int)h(len\);)240 4052 y(int)g(in_word_set)e(\(char)h(*str,)g(int)h +(len\);)125 4312 y Fm(By)e(default,)j(the)d(generated)h +Fk(hash)e Fm(function)f(returns)h(an)h(in)m(teger)g(v)-5 +b(alue)45 b(created)h(b)m(y)f(adding)e Fh(len)h Fm(to)0 +4437 y(sev)m(eral)c(user-sp)s(eci\014ed)e Fh(str)46 b +Fm(k)m(ey)40 b(p)s(ositions)e(indexed)g(in)m(to)i(an)g +Fh(asso)s(ciated)g(v)-5 b(alues)43 b Fm(table)c(stored)h(in)f(a)h(lo)s +(cal)0 4561 y(static)e(arra)m(y)-8 b(.)63 b(The)37 b(asso)s(ciated)h(v) +-5 b(alues)37 b(table)g(is)g(constructed)g(in)m(ternally)f(b)m(y)h +Fk(gperf)f Fm(and)h(later)h(output)f(as)0 4686 y(a)44 +b(static)h(lo)s(cal)e(C)h(arra)m(y)g(called)f Fh(hash)p +1399 4686 28 4 v 32 w(table)5 b Fm(;)51 b(its)44 b(meaning)f(and)g +(prop)s(erties)g(are)h(describ)s(ed)e(b)s(elo)m(w.)81 +b(See)0 4810 y(Chapter)32 b(7)h([Implemen)m(tation],)h(page)f(29.)49 +b(The)33 b(relev)-5 b(an)m(t)33 b(k)m(ey)g(p)s(ositions)e(are)i(sp)s +(eci\014ed)e(via)i(the)g(`)p Fk(-k)p Fm(')f(option)0 +4935 y(when)d(running)f Fk(gperf)p Fm(,)h(as)i(detailed)e(in)g(the)i +Fh(Options)i Fm(section)d(b)s(elo)m(w.)40 b(See)31 b(Chapter)e(4)i +([Options],)f(page)h(19.)125 5215 y(Tw)m(o)39 b(options,)i(`)p +Fk(-g)p Fm(')f(\(assume)f(y)m(ou)h(are)g(compiling)d(with)h(GNU)i(C)g +(and)e(its)h Fk(inline)f Fm(feature\))i(and)f(`)p Fk(-a)p +Fm(')0 5340 y(\(assume)30 b(ANSI)g(C-st)m(yle)h(function)e(protot)m(yp) +s(es\),)j(alter)e(the)g(con)m(ten)m(t)j(of)d(b)s(oth)g(the)g(generated) +i Fk(hash)d Fm(and)h Fk(in_)p eop +%%Page: 17 19 +17 18 bop 0 -116 a Fm(Chapter)30 b(3:)41 b(High-Lev)m(el)30 +b(Description)g(of)g(GNU)h Fk(gperf)1820 b Fm(17)0 366 +y Fk(word_set)24 b Fm(routines.)38 b(Ho)m(w)m(ev)m(er,)29 +b(function)24 b Fk(in_word_set)f Fm(ma)m(y)j(b)s(e)g(mo)s(di\014ed)d +(more)j(extensiv)m(ely)-8 b(,)27 b(in)e(resp)s(onse)0 +491 y(to)31 b(y)m(our)f(option)g(settings.)41 b(The)30 +b(options)g(that)g(a\013ect)i(the)f Fk(in_word_set)c +Fm(structure)j(are:)180 790 y(`)p Fk(-t)p Fm(')334 b(Mak)m(e)32 +b(use)e(of)h(the)f(user-de\014ned)f Fk(struct)p Fm(.)180 +964 y(`)p Fk(-S)h Fh(total)h(switc)m(h)f(statemen)m(ts)t +Fm(')660 1089 y(Generate)h(1)g(or)f(more)g(C)g Fk(switch)e +Fm(statemen)m(t)k(rather)e(than)g(use)g(a)g(large,)g(\(and)g(p)s(oten)m +(tially)660 1213 y(sparse\))j(static)g(arra)m(y)-8 b(.)50 +b(Although)32 b(the)h(exact)i(time)d(and)g(space)i(sa)m(vings)f(of)g +(this)f(approac)m(h)660 1338 y(v)-5 b(ary)42 b(according)g(to)i(y)m +(our)e(C)g(compiler's)f(degree)i(of)f(optimization,)j(this)c(metho)s(d) +h(often)660 1462 y(results)29 b(in)g(smaller)g(and)h(faster)h(co)s(de.) +125 1761 y(If)20 b(the)h(`)p Fk(-t)p Fm(')f(and)h(`)p +Fk(-S)p Fm(')f(options)g(are)i(omitted,)h(the)e(default)f(action)h(is)e +(to)j(generate)g(a)f Fk(char)30 b(*)20 b Fm(arra)m(y)h(con)m(taining)0 +1886 y(the)32 b(k)m(eys,)g(together)h(with)e(additional)e(n)m(ull)h +(strings)g(used)h(for)g(padding)f(the)h(arra)m(y)-8 b(.)46 +b(By)31 b(exp)s(erimen)m(ting)f(with)0 2010 y(the)e(v)-5 +b(arious)27 b(input)f(and)h(output)g(options,)h(and)g(timing)e(the)i +(resulting)e(C)h(co)s(de,)i(y)m(ou)f(can)g(determine)f(the)h(b)s(est)0 +2135 y(option)i(c)m(hoices)h(for)f(di\013eren)m(t)g(k)m(eyw)m(ord)h +(set)g(c)m(haracteristics.)p eop +%%Page: 18 20 +18 19 bop 0 -116 a Fm(18)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Page: 19 21 +19 20 bop 0 -116 a Fm(Chapter)30 b(4:)41 b(Options)29 +b(to)i(the)g Fk(gperf)d Fm(Utilit)m(y)2203 b(19)0 366 +y Fj(4)80 b(Options)30 b(to)g(the)f Fg(gperf)h Fj(Utilit)l(y)125 +739 y Fm(There)38 b(are)i Fh(man)m(y)47 b Fm(options)39 +b(to)h Fk(gperf)p Fm(.)66 b(They)39 b(w)m(ere)h(added)e(to)i(mak)m(e)h +(the)e(program)g(more)h(con)m(v)m(enien)m(t)0 863 y(for)34 +b(use)f(with)g(real)g(applications.)49 b(\\On-line")33 +b(help)f(is)h(readily)g(a)m(v)-5 b(ailable)33 b(via)g(the)h(`)p +Fk(-h)p Fm(')g(option.)51 b(Here)34 b(is)f(the)0 988 +y(complete)e(list)e(of)h(options.)0 1435 y Fi(4.1)68 +b(Options)31 b(that)g(a\013ect)g(In)l(terpretation)i(of)d(the)h(Input)f +(File)180 1733 y Fm(`)p Fk(-e)g Fh(k)m(eyw)m(ord)h(delimiter)d(list)r +Fm(')660 1858 y(Allo)m(ws)23 b(the)h(user)g(to)h(pro)m(vide)e(a)h +(string)f(con)m(taining)h(delimiters)d(used)j(to)h(separate)g(k)m(eyw)m +(ords)660 1982 y(from)j(their)g(attributes.)40 b(The)29 +b(default)f(is)g Fk(")p Fm(,)p Fk(\\)p Fm(n)p Fk(")p +Fm(.)39 b(This)27 b(option)i(is)f(essen)m(tial)g(if)g(y)m(ou)h(w)m(an)m +(t)h(to)660 2107 y(use)g(k)m(eyw)m(ords)h(that)f(ha)m(v)m(e)i(em)m(b)s +(edded)d(commas)i(or)f(newlines.)38 b(One)30 b(useful)f(tric)m(k)h(is)f +(to)i(use)660 2232 y(-e'T)-8 b(AB',)32 b(where)e(T)-8 +b(AB)31 b(is)f(the)g(literal)f(tab)i(c)m(haracter.)180 +2405 y(`)p Fk(-t)p Fm(')334 b(Allo)m(ws)39 b(y)m(ou)h(to)g(include)e(a) +i Fk(struct)e Fm(t)m(yp)s(e)i(declaration)g(for)f(generated)i(co)s(de.) +69 b(An)m(y)40 b(text)660 2530 y(b)s(efore)h(a)h(pair)e(of)i +(consecutiv)m(e)g(\045\045)f(is)g(consider)f(part)h(of)h(the)g(t)m(yp)s +(e)f(declaration.)74 b(Key)660 2654 y(w)m(ords)32 b(and)g(additional)e +(\014elds)h(ma)m(y)j(follo)m(w)d(this,)i(one)f(group)g(of)h(\014elds)e +(p)s(er)h(line.)45 b(A)33 b(set)g(of)660 2779 y(examples)i(for)h +(generating)g(p)s(erfect)g(hash)f(tables)h(and)f(functions)g(for)g +(Ada,)j(C,)e(and)f(G)p Fk(++)p Fm(,)660 2903 y(P)m(ascal,)c(and)f(Mo)s +(dula)f(2)i(and)f(3)h(reserv)m(ed)f(w)m(ords)g(are)h(distributed)c +(with)i(this)h(release.)0 3350 y Fi(4.2)68 b(Options)31 +b(to)g(sp)t(ecify)f(the)h(Language)g(for)f(the)h(Output)f(Co)t(de)180 +3649 y Fm(`)p Fk(-L)g Fh(generated)h(language)g(name)5 +b Fm(')660 3773 y(Instructs)35 b Fk(gperf)f Fm(to)i(generate)h(co)s(de) +f(in)e(the)i(language)g(sp)s(eci\014ed)d(b)m(y)j(the)g(option's)f +(argu-)660 3898 y(men)m(t.)41 b(Languages)31 b(handled)e(are)i(curren)m +(tly:)840 4072 y(`)p Fk(KR-C)p Fm(')238 b(Old-st)m(yle)43 +b(K&R)g(C.)h(This)e(language)i(is)f(understo)s(o)s(d)f(b)m(y)i(old-st)m +(yle)f(C)1320 4196 y(compilers)25 b(and)i(ANSI)f(C)h(compilers,)f(but)g +(ANSI)h(C)g(compilers)e(ma)m(y)j(\015ag)1320 4321 y(w)m(arnings)h(\(or) +i(ev)m(en)g(errors\))f(b)s(ecause)g(of)h(lac)m(king)f(`)p +Fk(const)p Fm('.)840 4494 y(`)p Fk(C)p Fm(')382 b(Common)35 +b(C.)g(This)f(language)h(is)g(understo)s(o)s(d)e(b)m(y)i(ANSI)g(C)g +(compilers,)1320 4619 y(and)44 b(also)g(b)m(y)g(old-st)m(yle)g(C)f +(compilers,)k(pro)m(vided)c(that)h(y)m(ou)h Fk(#define)1320 +4744 y(const)33 b Fm(to)i(empt)m(y)g(for)g(compilers)e(whic)m(h)g +(don't)i(kno)m(w)f(ab)s(out)g(this)g(k)m(ey-)1320 4868 +y(w)m(ord.)840 5042 y(`)p Fk(ANSI-C)p Fm(')142 b(ANSI)33 +b(C.)h(This)d(language)j(is)f(understo)s(o)s(d)f(b)m(y)h(ANSI)g(C)h +(compilers)e(and)1320 5166 y(C)p Fk(++)d Fm(compilers.)840 +5340 y(`)p Fk(C++)p Fm(')286 b(C)p Fk(++)p Fm(.)40 b(This)28 +b(language)j(is)f(understo)s(o)s(d)e(b)m(y)i(C)p Fk(++)g +Fm(compilers.)p eop +%%Page: 20 22 +20 21 bop 0 -116 a Fm(20)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)660 366 y Fm(The)f(default)f(is)h(C.)180 548 +y(`)p Fk(-a)p Fm(')334 b(This)25 b(option)h(is)f(supp)s(orted)g(for)h +(compatibilit)m(y)f(with)g(previous)g(releases)i(of)g +Fk(gperf)p Fm(.)38 b(It)26 b(do)s(es)660 672 y(not)31 +b(do)f(an)m(ything.)180 853 y(`)p Fk(-g)p Fm(')334 b(This)25 +b(option)h(is)f(supp)s(orted)g(for)h(compatibilit)m(y)f(with)g +(previous)g(releases)i(of)g Fk(gperf)p Fm(.)38 b(It)26 +b(do)s(es)660 978 y(not)31 b(do)f(an)m(ything.)0 1457 +y Fi(4.3)68 b(Options)31 b(for)f(\014ne)g(tuning)h(Details)h(in)e(the)h +(Output)f(Co)t(de)180 1762 y Fm(`)p Fk(-K)g Fh(k)m(ey)h(name)5 +b Fm(')660 1887 y(This)20 b(option)h(is)g(only)g(useful)f(when)h +(option)h(`)p Fk(-t)p Fm(')f(has)h(b)s(een)f(giv)m(en.)38 +b(By)22 b(default,)h(the)f(program)660 2012 y(assumes)28 +b(the)i(structure)e(comp)s(onen)m(t)h(iden)m(ti\014er)e(for)i(the)g(k)m +(eyw)m(ord)g(is)f(`)p Fk(name)p Fm('.)39 b(This)27 b(option)660 +2136 y(allo)m(ws)34 b(an)h(arbitrary)e(c)m(hoice)i(of)g(iden)m +(ti\014er)e(for)h(this)g(comp)s(onen)m(t,)i(although)e(it)h(still)d(m)m +(ust)660 2261 y(o)s(ccur)e(as)h(the)f(\014rst)g(\014eld)f(in)g(y)m(our) +h(supplied)d Fk(struct)p Fm(.)180 2442 y(`)p Fk(-H)j +Fh(hash)g(function)f(name)5 b Fm(')660 2566 y(Allo)m(ws)31 +b(y)m(ou)h(to)h(sp)s(ecify)d(the)i(name)g(for)f(the)h(generated)h(hash) +e(function.)44 b(Default)32 b(name)g(is)660 2691 y(`)p +Fk(hash)p Fm('.)40 b(This)29 b(option)g(p)s(ermits)g(the)i(use)f(of)g +(t)m(w)m(o)i(hash)e(tables)g(in)f(the)h(same)h(\014le.)180 +2872 y(`)p Fk(-N)f Fh(lo)s(okup)f(function)g(name)5 b +Fm(')660 2996 y(Allo)m(ws)31 b(y)m(ou)i(to)g(sp)s(ecify)e(the)i(name)f +(for)g(the)h(generated)g(lo)s(okup)e(function.)45 b(Default)33 +b(name)660 3121 y(is)27 b(`)p Fk(in_word_set)p Fm('.)37 +b(This)26 b(option)h(p)s(ermits)f(completely)h(automatic)i(generation)f +(of)g(p)s(erfect)660 3246 y(hash)h(functions,)g(esp)s(ecially)g(when)g +(m)m(ultiple)e(generated)k(hash)f(functions)e(are)j(used)e(in)g(the)660 +3370 y(same)i(application.)180 3551 y(`)p Fk(-Z)f Fh(class)g(name)5 +b Fm(')660 3676 y(This)32 b(option)i(is)e(only)i(useful)e(when)h +(option)g(`)p Fk(-L)d(C++)p Fm(')j(has)h(b)s(een)f(giv)m(en.)52 +b(It)34 b(allo)m(ws)f(y)m(ou)h(to)660 3800 y(sp)s(ecify)29 +b(the)i(name)f(of)h(generated)g(C)p Fk(++)e Fm(class.)41 +b(Default)30 b(name)h(is)e Fk(Perfect_Hash)p Fm(.)180 +3981 y(`)p Fk(-7)p Fm(')334 b(This)29 b(option)i(sp)s(eci\014es)f(that) +h(all)f(strings)g(that)i(will)c(b)s(e)j(passed)f(as)i(argumen)m(ts)f +(to)h(the)f(gen-)660 4106 y(erated)e(hash)f(function)g(and)g(the)h +(generated)g(lo)s(okup)f(function)f(will)f(solely)i(consist)g(of)h +(7-bit)660 4231 y(ASCI)s(I)k(c)m(haracters)j(\(c)m(haracters)g(in)e +(the)g(range)h(0..127\).)56 b(\(Note)36 b(that)f(the)g(ANSI)f(C)h +(func-)660 4355 y(tions)k Fk(isalnum)e Fm(and)i Fk(isgraph)f +Fm(do)h Fh(not)j Fm(guaran)m(tee)e(that)h(a)e(c)m(haracter)i(is)e(in)f +(this)g(range.)660 4480 y(Only)e(an)h(explicit)f(test)i(lik)m(e)f(`)p +Fk(c)30 b(>=)g('A')f(&&)h(c)g(<=)g('Z')p Fm(')37 b(guaran)m(tees)h +(this.\))61 b(This)36 b(w)m(as)i(the)660 4604 y(default)29 +b(in)g(earlier)g(v)m(ersions)g(of)h Fk(gperf)p Fm(;)f(no)m(w)h(the)g +(default)f(is)g(to)i(assume)e(8-bit)h(c)m(haracters.)180 +4785 y(`)p Fk(-c)p Fm(')334 b(Generates)33 b(C)f(co)s(de)g(that)g(uses) +g(the)g Fk(strncmp)e Fm(function)h(to)h(p)s(erform)f(string)g +(comparisons.)660 4910 y(The)f(default)f(action)i(is)f(to)h(use)f +Fk(strcmp)p Fm(.)180 5091 y(`)p Fk(-C)p Fm(')334 b(Mak)m(es)27 +b(the)f(con)m(ten)m(ts)h(of)f(all)e(generated)j(lo)s(okup)d(tables)h +(constan)m(t,)j(i.e.,)f(\\readonly".)39 b(Man)m(y)660 +5215 y(compilers)21 b(can)i(generate)h(more)f(e\016cien)m(t)g(co)s(de)g +(for)f(this)f(b)m(y)i(putting)e(the)i(tables)g(in)e(readonly)660 +5340 y(memory)-8 b(.)p eop +%%Page: 21 23 +21 22 bop 0 -116 a Fm(Chapter)30 b(4:)41 b(Options)29 +b(to)i(the)g Fk(gperf)d Fm(Utilit)m(y)2203 b(21)180 366 +y(`)p Fk(-E)p Fm(')334 b(De\014ne)24 b(constan)m(t)h(v)-5 +b(alues)23 b(using)f(an)i(en)m(um)f(lo)s(cal)g(to)i(the)e(lo)s(okup)g +(function)f(rather)i(than)f(with)660 491 y(#de\014nes.)46 +b(This)31 b(also)i(means)f(that)h(di\013eren)m(t)g(lo)s(okup)e +(functions)g(can)i(reside)e(in)h(the)h(same)660 616 y(\014le.)40 +b(Thanks)29 b(to)i(James)g(Clark)e Fk()p +Fm(.)180 781 y(`)p Fk(-I)p Fm(')334 b(Include)40 b(the)h(necessary)h +(system)g(include)d(\014le,)k Fk()p Fm(,)f(at)g(the)g(b)s +(eginning)c(of)k(the)660 905 y(co)s(de.)52 b(By)35 b(default,)f(this)f +(is)h(not)g(done;)i(the)e(user)g(m)m(ust)g(include)e(this)h(header)h +(\014le)f(himself)660 1030 y(to)e(allo)m(w)f(compilation)f(of)h(the)h +(co)s(de.)180 1195 y(`)p Fk(-G)p Fm(')334 b(Generate)25 +b(the)g(static)f(table)g(of)g(k)m(eyw)m(ords)g(as)h(a)f(static)g +(global)g(v)-5 b(ariable,)24 b(rather)g(than)g(hiding)660 +1320 y(it)30 b(inside)e(of)j(the)f(lo)s(okup)f(function)g(\(whic)m(h)h +(is)f(the)i(default)e(b)s(eha)m(vior\).)180 1485 y(`)p +Fk(-W)h Fh(hash)g(table)g(arra)m(y)h(name)5 b Fm(')660 +1609 y(Allo)m(ws)28 b(y)m(ou)h(to)h(sp)s(ecify)e(the)h(name)g(for)g +(the)g(generated)h(arra)m(y)g(con)m(taining)e(the)i(hash)e(table.)660 +1734 y(Default)g(name)g(is)e(`)p Fk(wordlist)p Fm('.)38 +b(This)26 b(option)i(p)s(ermits)e(the)h(use)h(of)g(t)m(w)m(o)h(hash)e +(tables)g(in)g(the)660 1858 y(same)k(\014le,)e(ev)m(en)j(when)d(the)i +(option)e(`)p Fk(-G)p Fm(')i(is)e(giv)m(en.)180 2023 +y(`)p Fk(-S)h Fh(total)h(switc)m(h)f(statemen)m(ts)t +Fm(')660 2148 y(Causes)45 b(the)h(generated)g(C)f(co)s(de)h(to)g(use)g +(a)f Fk(switch)f Fm(statemen)m(t)k(sc)m(heme,)i(rather)45 +b(than)660 2273 y(an)g(arra)m(y)h(lo)s(okup)e(table.)86 +b(This)44 b(can)h(lead)g(to)h(a)g(reduction)f(in)f(b)s(oth)g(time)i +(and)e(space)660 2397 y(requiremen)m(ts)24 b(for)i(some)f(k)m +(ey\014les.)39 b(The)25 b(argumen)m(t)h(to)g(this)e(option)h +(determines)f(ho)m(w)i(man)m(y)660 2522 y Fk(switch)k +Fm(statemen)m(ts)k(are)e(generated.)46 b(A)32 b(v)-5 +b(alue)32 b(of)g(1)g(generates)h(1)f Fk(switch)f Fm(con)m(taining)g +(all)660 2646 y(the)26 b(elemen)m(ts,)h(a)g(v)-5 b(alue)25 +b(of)h(2)g(generates)i(2)e(tables)g(with)e(1/2)j(the)g(elemen)m(ts)f +(in)e(eac)m(h)j Fk(switch)p Fm(,)660 2771 y(etc.)40 b(This)25 +b(is)g(useful)f(since)i(man)m(y)g(C)g(compilers)f(cannot)h(correctly)h +(generate)h(co)s(de)e(for)g(large)660 2895 y Fk(switch)j +Fm(statemen)m(ts.)44 b(This)29 b(option)h(w)m(as)h(inspired)d(in)h +(part)i(b)m(y)g(Keith)f(Bostic's)h(original)e(C)660 3020 +y(program.)180 3185 y(`)p Fk(-T)p Fm(')334 b(Prev)m(en)m(ts)31 +b(the)g(transfer)f(of)h(the)g(t)m(yp)s(e)g(declaration)f(to)h(the)g +(output)f(\014le.)40 b(Use)31 b(this)f(option)g(if)660 +3309 y(the)h(t)m(yp)s(e)f(is)g(already)f(de\014ned)h(elsewhere.)180 +3475 y(`)p Fk(-p)p Fm(')334 b(This)25 b(option)h(is)f(supp)s(orted)g +(for)h(compatibilit)m(y)f(with)g(previous)g(releases)i(of)g +Fk(gperf)p Fm(.)38 b(It)26 b(do)s(es)660 3599 y(not)31 +b(do)f(an)m(ything.)0 4029 y Fi(4.4)68 b(Options)31 b(for)f(c)l +(hanging)h(the)g(Algorithms)g(emplo)l(y)l(ed)h(b)l(y)e +Ff(gperf)180 4323 y Fm(`)p Fk(-k)g Fh(k)m(eys)t Fm(')131 +b(Allo)m(ws)23 b(selection)g(of)h(the)g(c)m(haracter)h(k)m(ey)g(p)s +(ositions)d(used)g(in)h(the)h(k)m(eyw)m(ords')g(hash)f(function.)660 +4448 y(The)28 b(allo)m(w)m(able)g(c)m(hoices)h(range)g(b)s(et)m(w)m +(een)g(1-126,)i(inclusiv)m(e.)38 b(The)27 b(p)s(ositions)g(are)h +(separated)660 4572 y(b)m(y)d(commas,)j(e.g.,)g(`)p Fk(-k)i(9,4,13,14)p +Fm(';)25 b(ranges)h(ma)m(y)g(b)s(e)e(used,)i(e.g.,)i(`)p +Fk(-k)i(2-7)p Fm(';)d(and)e(p)s(ositions)660 4697 y(ma)m(y)j(o)s(ccur)f +(in)f(an)m(y)h(order.)39 b(F)-8 b(urthermore,)28 b(the)g(meta-c)m +(haracter)i('*')e(causes)g(the)f(generated)660 4822 y(hash)i(function)g +(to)h(consider)f Fc(all)i Fm(c)m(haracter)g(p)s(ositions)d(in)g(eac)m +(h)j(k)m(ey)-8 b(,)32 b(whereas)e('$')g(instructs)660 +4946 y(the)f(hash)f(function)g(to)h(use)g(the)g(\\\014nal)f(c)m +(haracter")j(of)e(a)g(k)m(ey)h(\(this)e(is)g(the)h(only)f(w)m(a)m(y)i +(to)f(use)660 5071 y(a)i(c)m(haracter)h(p)s(osition)c(greater)k(than)e +(126,)i(inciden)m(tally\).)660 5215 y(F)-8 b(or)29 b(instance,)f(the)g +(option)f(`)p Fk(-k)j(1,2,4,6-10,'$')p Fm(')25 b(generates)k(a)f(hash)f +(function)g(that)h(con-)660 5340 y(siders)38 b(p)s(ositions)g +(1,2,4,6,7,8,9,10,)49 b(plus)38 b(the)i(last)f(c)m(haracter)j(in)d(eac) +m(h)i(k)m(ey)f(\(whic)m(h)f(ma)m(y)p eop +%%Page: 22 24 +22 23 bop 0 -116 a Fm(22)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)660 366 y Fm(di\013er)j(for)h(eac)m(h)h(k)m(ey)-8 +b(,)38 b(ob)m(viously\).)54 b(Keys)35 b(with)f(length)h(less)f(than)h +(the)h(indicated)d(k)m(ey)j(p)s(o-)660 491 y(sitions)j(w)m(ork)h(prop)s +(erly)-8 b(,)42 b(since)d(selected)i(k)m(ey)g(p)s(ositions)e(exceeding) +h(the)h(k)m(ey)g(length)f(are)660 616 y(simply)28 b(not)j(referenced)f +(in)f(the)h(hash)g(function.)180 843 y(`)p Fk(-l)p Fm(')334 +b(Compare)32 b(k)m(ey)g(lengths)f(b)s(efore)g(trying)g(a)h(string)f +(comparison.)44 b(This)30 b(migh)m(t)i(cut)g(do)m(wn)f(on)660 +967 y(the)23 b(n)m(um)m(b)s(er)e(of)h(string)f(comparisons)h(made)g +(during)e(the)j(lo)s(okup,)g(since)e(k)m(eys)i(with)e(di\013eren)m(t) +660 1092 y(lengths)i(are)h(nev)m(er)g(compared)f(via)g +Fk(strcmp)p Fm(.)37 b(Ho)m(w)m(ev)m(er,)27 b(using)22 +b(`)p Fk(-l)p Fm(')i(migh)m(t)f(greatly)h(increase)660 +1216 y(the)33 b(size)f(of)g(the)h(generated)h(C)e(co)s(de)g(if)g(the)g +(lo)s(okup)f(table)h(range)h(is)f(large)g(\(whic)m(h)g(implies)660 +1341 y(that)26 b(the)f(switc)m(h)g(option)g(`)p Fk(-S)p +Fm(')g(is)f(not)i(enabled\),)g(since)e(the)i(length)f(table)g(con)m +(tains)g(as)h(man)m(y)660 1465 y(elemen)m(ts)31 b(as)f(there)h(are)g +(en)m(tries)f(in)f(the)h(lo)s(okup)f(table.)180 1692 +y(`)p Fk(-D)p Fm(')334 b(Handle)26 b(k)m(eyw)m(ords)g(whose)h(k)m(ey)g +(p)s(osition)d(sets)j(hash)f(to)h(duplicate)e(v)-5 b(alues.)39 +b(Duplicate)26 b(hash)660 1817 y(v)-5 b(alues)30 b(o)s(ccur)g(for)g(t)m +(w)m(o)i(reasons:)735 1993 y Fl(\017)60 b Fm(Since)33 +b Fk(gperf)f Fm(do)s(es)h(not)h(bac)m(ktrac)m(k)h(it)e(is)g(p)s +(ossible)e(for)i(it)h(to)g(pro)s(cess)f(all)f(y)m(our)i(input)840 +2117 y(k)m(eyw)m(ords)43 b(without)e(\014nding)g(a)i(unique)d(mapping)h +(for)h(eac)m(h)i(w)m(ord.)77 b(Ho)m(w)m(ev)m(er,)48 b(fre-)840 +2242 y(quen)m(tly)39 b(only)f(a)i(v)m(ery)f(small)f(n)m(um)m(b)s(er)g +(of)h(duplicates)f(o)s(ccur,)j(and)e(the)g(ma)5 b(jorit)m(y)40 +b(of)840 2366 y(k)m(eys)31 b(still)d(require)h(one)i(prob)s(e)e(in)m +(to)i(the)f(table.)735 2542 y Fl(\017)60 b Fm(Sometimes)45 +b(a)g(set)h(of)g(k)m(eys)f(ma)m(y)h(ha)m(v)m(e)h(the)e(same)g(names,)50 +b(but)44 b(p)s(ossess)g(di\013eren)m(t)840 2666 y(attributes.)39 +b(With)24 b(the)i(-D)g(option)f Fk(gperf)f Fm(treats)i(all)e(these)i(k) +m(eys)g(as)g(part)f(of)g(an)h(equiv-)840 2791 y(alence)31 +b(class)f(and)g(generates)i(a)e(p)s(erfect)h(hash)f(function)f(with)g +(m)m(ultiple)f(comparisons)840 2916 y(for)c(duplicate)e(k)m(eys.)39 +b(It)24 b(is)f(up)f(to)j(y)m(ou)f(to)h(completely)e(disam)m(biguate)g +(the)h(k)m(eyw)m(ords)g(b)m(y)840 3040 y(mo)s(difying)g(the)i +(generated)i(C)e(co)s(de.)39 b(Ho)m(w)m(ev)m(er,)30 b +Fk(gperf)24 b Fm(helps)h(y)m(ou)i(out)f(b)m(y)h(organizing)840 +3165 y(the)k(output.)660 3392 y(Option)26 b(`)p Fk(-D)p +Fm(')h(is)g(extremely)g(useful)f(for)h(certain)g(large)h(or)f(highly)e +(redundan)m(t)h(k)m(eyw)m(ord)i(sets,)660 3516 y(e.g.,)49 +b(assem)m(bler)44 b(instruction)e(op)s(co)s(des.)81 b(Using)43 +b(this)g(option)g(usually)f(means)i(that)h(the)660 3641 +y(generated)29 b(hash)e(function)f(is)h(no)h(longer)f(p)s(erfect.)40 +b(On)27 b(the)h(other)g(hand,)f(it)g(p)s(ermits)f Fk(gperf)660 +3765 y Fm(to)31 b(w)m(ork)g(on)f(k)m(eyw)m(ord)h(sets)f(that)h(it)f +(otherwise)g(could)g(not)g(handle.)180 3992 y(`)p Fk(-f)g +Fh(iteration)g(amoun)m(t)r Fm(')660 4117 y(Generate)38 +b(the)e(p)s(erfect)h(hash)e(function)g(\\fast".)61 b(This)34 +b(decreases)j Fk(gperf)p Fm('s)f(running)d(time)660 4241 +y(at)38 b(the)f(cost)h(of)f(minimizing)c(generated)38 +b(table-size.)60 b(The)36 b(iteration)h(amoun)m(t)g(represen)m(ts)660 +4366 y(the)29 b(n)m(um)m(b)s(er)f(of)h(times)g(to)g(iterate)h(when)e +(resolving)g(a)h(collision.)38 b(`0')30 b(means)f(iterate)h(b)m(y)f +(the)660 4490 y(n)m(um)m(b)s(er)22 b(of)h(k)m(eyw)m(ords.)38 +b(This)21 b(option)i(is)f(probably)f(most)i(useful)e(when)h(used)g(in)g +(conjunction)660 4615 y(with)29 b(options)h(`)p Fk(-D)p +Fm(')g(and/or)g(`)p Fk(-S)p Fm(')h(for)f Fh(large)35 +b Fm(k)m(eyw)m(ord)c(sets.)180 4842 y(`)p Fk(-i)f Fh(initial)e(v)-5 +b(alue)5 b Fm(')660 4966 y(Pro)m(vides)36 b(an)g(initial)e +Fh(v)-5 b(alue)41 b Fm(for)36 b(the)h(asso)s(ciate)g(v)-5 +b(alues)36 b(arra)m(y)-8 b(.)59 b(Default)37 b(is)e(0.)60 +b(Increasing)660 5091 y(the)39 b(initial)d(v)-5 b(alue)39 +b(helps)e(in\015ate)i(the)g(\014nal)e(table)i(size,)j(p)s(ossibly)36 +b(leading)h(to)j(more)f(time)660 5215 y(e\016cien)m(t)e(k)m(eyw)m(ord)h +(lo)s(okups.)59 b(Note)38 b(that)g(this)e(option)g(is)g(not)h +(particularly)e(useful)g(when)660 5340 y(`)p Fk(-S)p +Fm(')30 b(is)g(used.)40 b(Also,)30 b(`)p Fk(-i)p Fm(')g(is)g(o)m(v)m +(erriden)g(when)f(the)h(`)p Fk(-r)p Fm(')h(option)f(is)f(used.)p +eop +%%Page: 23 25 +23 24 bop 0 -116 a Fm(Chapter)30 b(4:)41 b(Options)29 +b(to)i(the)g Fk(gperf)d Fm(Utilit)m(y)2203 b(23)180 366 +y(`)p Fk(-j)30 b Fh(jump)f(v)-5 b(alue)5 b Fm(')660 491 +y(A\013ects)35 b(the)f(\\jump)f(v)-5 b(alue",)36 b(i.e.,)f(ho)m(w)f +(far)g(to)g(adv)-5 b(ance)35 b(the)f(asso)s(ciated)h(c)m(haracter)g(v) +-5 b(alue)660 616 y(up)s(on)30 b(collisions.)41 b Fh(Jump)30 +b(v)-5 b(alue)36 b Fm(is)31 b(rounded)f(up)g(to)j(an)e(o)s(dd)f(n)m(um) +m(b)s(er,)h(the)h(default)e(is)h(5.)44 b(If)660 740 y(the)31 +b Fh(jump)d(v)-5 b(alue)35 b Fm(is)30 b(0)h Fk(gperf)d +Fm(jumps)h(b)m(y)h(random)g(amoun)m(ts.)180 908 y(`)p +Fk(-n)p Fm(')334 b(Instructs)36 b(the)i(generator)g(not)f(to)h(include) +d(the)j(length)e(of)h(a)h(k)m(eyw)m(ord)g(when)e(computing)660 +1033 y(its)27 b(hash)g(v)-5 b(alue.)39 b(This)26 b(ma)m(y)i(sa)m(v)m(e) +h(a)f(few)f(assem)m(bly)g(instructions)f(in)g(the)i(generated)g(lo)s +(okup)660 1158 y(table.)180 1326 y(`)p Fk(-o)p Fm(')334 +b(Reorders)38 b(the)h(k)m(eyw)m(ords)f(b)m(y)h(sorting)e(the)i(k)m(eyw) +m(ords)g(so)f(that)h(frequen)m(tly)f(o)s(ccuring)f(k)m(ey)660 +1450 y(p)s(osition)h(set)j(comp)s(onen)m(ts)f(app)s(ear)f(\014rst.)69 +b(A)40 b(second)h(reordering)d(pass)i(follo)m(ws)f(so)h(that)660 +1575 y(k)m(eys)29 b(with)f(\\already)h(determined)e(v)-5 +b(alues")29 b(are)g(placed)g(to)m(w)m(ards)g(the)g(fron)m(t)g(of)g(the) +g(k)m(eylist.)660 1700 y(This)e(ma)m(y)i(decrease)h(the)e(time)h +(required)d(to)k(generate)g(a)f(p)s(erfect)f(hash)g(function)f(for)i +(man)m(y)660 1824 y(k)m(eyw)m(ord)i(sets,)h(and)f(also)g(pro)s(duce)f +(more)h(minimal)d(p)s(erfect)j(hash)f(functions.)41 b(The)31 +b(reason)660 1949 y(for)h(this)g(is)f(that)i(the)g(reordering)e(helps)g +(prune)g(the)h(searc)m(h)h(time)g(b)m(y)f(handling)e(inevitable)660 +2073 y(collisions)20 b(early)j(in)f(the)h(searc)m(h)g(pro)s(cess.)38 +b(On)22 b(the)h(other)g(hand,)h(if)e(the)h(n)m(um)m(b)s(er)f(of)h(k)m +(eyw)m(ords)660 2198 y(is)33 b Fh(v)m(ery)42 b Fm(large)33 +b(using)f(`)p Fk(-o)p Fm(')i(ma)m(y)g Fh(increase)39 +b Fk(gperf)p Fm('s)32 b(execution)i(time,)g(since)f(collisions)f(will) +660 2322 y(b)s(egin)h(earlier)g(and)h(con)m(tin)m(ue)h(throughout)f +(the)g(remainder)f(of)h(k)m(eyw)m(ord)h(pro)s(cessing.)52 +b(See)660 2447 y(Cic)m(helli's)28 b(pap)s(er)h(from)h(the)h(Jan)m(uary) +f(1980)i(Comm)m(unications)d(of)h(the)h(A)m(CM)g(for)f(details.)180 +2615 y(`)p Fk(-r)p Fm(')334 b(Utilizes)22 b(randomness)h(to)h +(initialize)d(the)i(asso)s(ciated)h(v)-5 b(alues)23 b(table.)38 +b(This)22 b(frequen)m(tly)g(gener-)660 2740 y(ates)27 +b(solutions)e(faster)i(than)f(using)e(deterministic)h(initialization)e +(\(whic)m(h)i(starts)i(all)e(asso)s(ci-)660 2864 y(ated)g(v)-5 +b(alues)23 b(at)i(0\).)39 b(F)-8 b(urthermore,)26 b(using)c(the)j +(randomization)d(option)i(generally)f(increases)660 2989 +y(the)32 b(size)f(of)g(the)h(table.)43 b(If)31 b Fk(gperf)f +Fm(has)h(di\016cultly)e(with)h(a)h(certain)h(k)m(eyw)m(ord)f(set)h(try) +f(using)660 3113 y(`)p Fk(-r)p Fm(')f(or)h(`)p Fk(-D)p +Fm('.)180 3282 y(`)p Fk(-s)f Fh(size-m)m(ultiple)5 b +Fm(')660 3406 y(A\013ects)27 b(the)g(size)f(of)g(the)h(generated)g +(hash)f(table.)39 b(The)26 b(n)m(umeric)f(argumen)m(t)h(for)g(this)f +(option)660 3531 y(indicates)f(\\ho)m(w)h(man)m(y)g(times)g(larger)g +(or)g(smaller")f(the)h(maxim)m(um)f(asso)s(ciated)h(v)-5 +b(alue)25 b(range)660 3655 y(should)32 b(b)s(e,)k(in)d(relationship)f +(to)j(the)g(n)m(um)m(b)s(er)e(of)h(k)m(eys.)54 b(If)34 +b(the)h Fh(size-m)m(ultiple)i Fm(is)d(negativ)m(e)660 +3780 y(the)g(maxim)m(um)e(asso)s(ciated)i(v)-5 b(alue)32 +b(is)h(calculated)g(b)m(y)g Fh(dividing)38 b Fm(it)33 +b(in)m(to)h(the)f(total)h(n)m(um)m(b)s(er)660 3904 y(of)29 +b(k)m(eys.)41 b(F)-8 b(or)29 b(example,)g(a)g(v)-5 b(alue)29 +b(of)g(3)g(means)f(\\allo)m(w)h(the)g(maxim)m(um)f(asso)s(ciated)h(v)-5 +b(alue)28 b(to)660 4029 y(b)s(e)i(ab)s(out)g(3)h(times)f(larger)g(than) +g(the)g(n)m(um)m(b)s(er)f(of)i(input)d(k)m(eys".)660 +4175 y(Con)m(v)m(ersely)-8 b(,)29 b(a)g(v)-5 b(alue)27 +b(of)h(-3)h(means)f(\\allo)m(w)g(the)g(maxim)m(um)f(asso)s(ciated)i(v) +-5 b(alue)27 b(to)i(b)s(e)e(ab)s(out)660 4300 y(3)38 +b(times)g(smaller)e(than)i(the)g(n)m(um)m(b)s(er)e(of)i(input)e(k)m +(eys".)65 b(Negativ)m(e)40 b(v)-5 b(alues)37 b(are)h(useful)e(for)660 +4424 y(limiting)27 b(the)j(o)m(v)m(erall)h(size)f(of)g(the)g(generated) +h(hash)e(table,)i(though)e(this)g(usually)f(increases)660 +4549 y(the)j(n)m(um)m(b)s(er)e(of)h(duplicate)f(hash)h(v)-5 +b(alues.)660 4695 y(If)44 b(`generate)j(switc)m(h')e(option)f(`)p +Fk(-S)p Fm(')h(is)f Fh(not)j Fm(enabled,)g(the)e(maxim)m(um)f(asso)s +(ciated)h(v)-5 b(alue)660 4820 y(in\015uences)32 b(the)h(static)h(arra) +m(y)g(table)f(size,)h(and)f(a)h(larger)f(table)g(should)e(decrease)k +(the)e(time)660 4944 y(required)c(for)h(an)g(unsuccessful)e(searc)m(h,) +j(at)g(the)g(exp)s(ense)f(of)g(extra)i(table)e(space.)660 +5091 y(The)c(default)g(v)-5 b(alue)26 b(is)g(1,)i(th)m(us)e(the)h +(default)f(maxim)m(um)f(asso)s(ciated)i(v)-5 b(alue)26 +b(ab)s(out)h(the)g(same)660 5215 y(size)i(as)g(the)g(n)m(um)m(b)s(er)f +(of)h(k)m(eys)g(\(for)g(e\016ciency)-8 b(,)30 b(the)f(maxim)m(um)f +(asso)s(ciated)h(v)-5 b(alue)28 b(is)g(alw)m(a)m(ys)660 +5340 y(rounded)f(up)h(to)h(a)g(p)s(o)m(w)m(er)f(of)h(2\).)41 +b(The)28 b(actual)h(table)f(size)h(ma)m(y)g(v)-5 b(ary)29 +b(somewhat,)g(since)f(this)p eop +%%Page: 24 26 +24 25 bop 0 -116 a Fm(24)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)660 366 y Fm(tec)m(hnique)e(is)f(essen)m(tially)h(a)g +(heuristic.)39 b(In)28 b(particular,)g(setting)i(this)e(v)-5 +b(alue)29 b(to)s(o)h(high)d(slo)m(ws)660 491 y(do)m(wn)f +Fk(gperf)p Fm('s)f(run)m(time,)i(since)f(it)g(m)m(ust)g(searc)m(h)i +(through)e(a)h(m)m(uc)m(h)f(larger)h(range)g(of)f(v)-5 +b(alues.)660 616 y(Judicious)28 b(use)i(of)g(the)h(`)p +Fk(-f)p Fm(')f(option)g(helps)f(alleviate)h(this)f(o)m(v)m(erhead,)j +(ho)m(w)m(ev)m(er.)0 1064 y Fi(4.5)68 b(Informativ)l(e)32 +b(Output)180 1363 y Fm(`)p Fk(-h)p Fm(')334 b(Prin)m(ts)32 +b(a)i(short)g(summary)e(on)i(the)g(meaning)e(of)i(eac)m(h)h(program)e +(option.)50 b(Ab)s(orts)33 b(further)660 1487 y(program)d(execution.) +180 1662 y(`)p Fk(-v)p Fm(')334 b(Prin)m(ts)29 b(out)i(the)f(curren)m +(t)h(v)m(ersion)e(n)m(um)m(b)s(er.)180 1836 y(`)p Fk(-d)p +Fm(')334 b(Enables)39 b(the)g(debugging)g(option.)68 +b(This)38 b(pro)s(duces)h(v)m(erb)s(ose)h(diagnostics)f(to)h +(\\standard)660 1961 y(error")27 b(when)f Fk(gperf)g +Fm(is)g(executing.)39 b(It)27 b(is)f(useful)g(b)s(oth)g(for)h(main)m +(taining)e(the)i(program)g(and)660 2085 y(for)32 b(determining)f +(whether)g(a)i(giv)m(en)g(set)g(of)f(options)g(is)f(actually)h(sp)s +(eeding)f(up)h(the)g(searc)m(h)660 2210 y(for)25 b(a)h(solution.)38 +b(Some)26 b(useful)e(information)g(is)g(dump)s(ed)g(at)i(the)g(end)f +(of)h(the)g(program)f(when)660 2334 y(the)31 b(`)p Fk(-d)p +Fm(')f(option)g(is)f(enabled.)p eop +%%Page: 25 27 +25 26 bop 0 -116 a Fm(Chapter)30 b(5:)41 b(Kno)m(wn)30 +b(Bugs)g(and)g(Limitations)e(with)h Fk(gperf)1697 b Fm(25)0 +366 y Fj(5)80 b(Kno)l(wn)29 b(Bugs)g(and)h(Limitations)i(with)e +Fg(gperf)125 740 y Fm(The)f(follo)m(wing)g(are)i(some)g(limitations)d +(with)h(the)h(curren)m(t)h(release)f(of)h Fk(gperf)p +Fm(:)75 1014 y Fl(\017)60 b Fm(The)26 b Fk(gperf)f Fm(utilit)m(y)g(is)h +(tuned)g(to)h(execute)h(quic)m(kly)-8 b(,)27 b(and)f(w)m(orks)h(quic)m +(kly)e(for)h(small)g(to)h(medium)e(size)h(data)180 1139 +y(sets)k(\(around)f(1000)j(k)m(eyw)m(ords\).)41 b(It)30 +b(is)f(extremely)h(useful)e(for)h(main)m(taining)f(p)s(erfect)i(hash)f +(functions)f(for)180 1263 y(compiler)j(k)m(eyw)m(ord)i(sets.)48 +b(Sev)m(eral)33 b(recen)m(t)h(enhancemen)m(ts)f(no)m(w)f(enable)g +Fk(gperf)g Fm(to)h(w)m(ork)g(e\016cien)m(tly)f(on)180 +1388 y(m)m(uc)m(h)26 b(larger)g(k)m(eyw)m(ord)h(sets)g(\(o)m(v)m(er)g +(15,000)i(k)m(eyw)m(ords\).)40 b(When)26 b(pro)s(cessing)f(large)h(k)m +(eyw)m(ord)h(sets)g(it)e(helps)180 1512 y(greatly)31 +b(to)g(ha)m(v)m(e)h(o)m(v)m(er)f(8)g(megs)g(of)f(RAM.)180 +1662 y(Ho)m(w)m(ev)m(er,)45 b(since)39 b Fk(gperf)g Fm(do)s(es)g(not)i +(bac)m(ktrac)m(k)h(no)e(guaran)m(teed)h(solution)d(o)s(ccurs)i(on)g(ev) +m(ery)h(run.)68 b(On)180 1786 y(the)35 b(other)h(hand,)f(it)g(is)f +(usually)f(easy)j(to)g(obtain)f(a)g(solution)f(b)m(y)h(v)-5 +b(arying)34 b(the)i(option)e(parameters.)56 b(In)180 +1911 y(particular,)37 b(try)g(the)g(`)p Fk(-r)p Fm(')f(option,)j(and)d +(also)h(try)f(c)m(hanging)h(the)g(default)f(argumen)m(ts)h(to)h(the)f +(`)p Fk(-s)p Fm(')g(and)180 2035 y(`)p Fk(-j)p Fm(')31 +b(options.)41 b(T)-8 b(o)31 b Fh(guaran)m(tee)37 b Fm(a)31 +b(solution,)f(use)g(the)h(`)p Fk(-D)p Fm(')g(and)f(`)p +Fk(-S)p Fm(')g(options,)h(although)f(the)h(\014nal)e(results)180 +2160 y(are)j(not)h(lik)m(ely)d(to)j(b)s(e)e(a)i Fh(p)s(erfect)g +Fm(hash)f(function)e(an)m(ymore!)47 b(Finally)-8 b(,)31 +b(use)g(the)h(`)p Fk(-f)p Fm(')g(option)g(if)f(y)m(ou)h(w)m(an)m(t)180 +2284 y Fk(gperf)d Fm(to)i(generate)h(the)f(p)s(erfect)f(hash)f +(function)g Fh(fast)p Fm(,)i(with)f(less)f(emphasis)g(on)h(making)g(it) +g(minimal.)75 2434 y Fl(\017)60 b Fm(The)28 b(size)g(of)g(the)h +(generate)h(static)f(k)m(eyw)m(ord)f(arra)m(y)h(can)g(get)g +Fh(extremely)37 b Fm(large)28 b(if)f(the)i(input)d(k)m(eyw)m(ord)j +(\014le)180 2558 y(is)k(large)g(or)h(if)f(the)g(k)m(eyw)m(ords)h(are)g +(quite)f(similar.)48 b(This)32 b(tends)h(to)i(slo)m(w)e(do)m(wn)g(the)h +(compilation)e(of)i(the)180 2683 y(generated)g(C)f(co)s(de,)h(and)e +Fh(greatly)42 b Fm(in\015ates)32 b(the)h(ob)5 b(ject)34 +b(co)s(de)f(size.)49 b(If)32 b(this)g(situation)g(o)s(ccurs,)i +(consider)180 2807 y(using)i(the)i(`)p Fk(-S)p Fm(')g(option)g(to)g +(reduce)g(data)g(size,)i(p)s(oten)m(tially)d(increasing)f(k)m(eyw)m +(ord)j(recognition)e(time)h(a)180 2932 y(negligible)32 +b(amoun)m(t.)52 b(Since)34 b(man)m(y)g(C)g(compilers)e(cannot)j +(correctly)g(generated)g(co)s(de)f(for)g(large)g(switc)m(h)180 +3056 y(statemen)m(ts)j(it)e(is)g(imp)s(ortan)m(t)f(to)i(qualify)e(the)h +Fh(-S)41 b Fm(option)35 b(with)f(an)h(appropriate)g(n)m(umerical)e +(argumen)m(t)180 3181 y(that)e(con)m(trols)g(the)f(n)m(um)m(b)s(er)f +(of)i(switc)m(h)f(statemen)m(ts)i(generated.)75 3330 +y Fl(\017)60 b Fm(The)31 b(maxim)m(um)f(n)m(um)m(b)s(er)g(of)h(k)m(ey)h +(p)s(ositions)e(selected)h(for)h(a)f(giv)m(en)h(k)m(ey)g(has)f(an)g +(arbitrary)f(limit)f(of)i(126.)180 3455 y(This)h(restriction)i(should)e +(b)s(e)h(remo)m(v)m(ed,)k(and)d(if)f(an)m(y)m(one)i(considers)e(this)g +(a)i(problem)e(write)g(me)h(and)g(let)180 3579 y(me)c(kno)m(w)h(so)f(I) +h(can)f(remo)m(v)m(e)i(the)f(constrain)m(t.)p eop +%%Page: 26 28 +26 27 bop 0 -116 a Fm(26)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Page: 27 29 +27 28 bop 0 -116 a Fm(Chapter)30 b(6:)41 b(Things)28 +b(Still)g(Left)j(to)g(Do)2433 b(27)0 366 y Fj(6)80 b(Things)30 +b(Still)j(Left)d(to)f(Do)125 740 y Fm(It)40 b(should)f(b)s(e)h +(\\relativ)m(ely")i(easy)f(to)h(replace)e(the)h(curren)m(t)g(p)s +(erfect)g(hash)f(function)f(algorithm)h(with)g(a)0 865 +y(more)35 b(exhaustiv)m(e)h(approac)m(h;)i(the)d(p)s(erfect)g(hash)g +(mo)s(dule)e(is)h(essen)m(tial)h(indep)s(enden)m(t)e(from)i(other)g +(program)0 989 y(mo)s(dules.)k(Additional)28 b(w)m(orth)m(while)h +(impro)m(v)m(emen)m(ts)h(include:)75 1263 y Fl(\017)60 +b Fm(Mak)m(e)33 b(the)e(algorithm)f(more)h(robust.)42 +b(A)m(t)32 b(presen)m(t,)f(the)h(program)e(halts)h(with)e(an)i(error)g +(diagnostic)f(if)g(it)180 1388 y(can't)j(\014nd)e(a)i(direct)f +(solution)f(and)h(the)h(`)p Fk(-D)p Fm(')f(option)g(is)g(not)g +(enabled.)46 b(A)33 b(more)g(comprehensiv)m(e,)f(alb)s(eit)180 +1512 y(computationally)26 b(exp)s(ensiv)m(e,)h(approac)m(h)g(w)m(ould)e +(emplo)m(y)i(bac)m(ktrac)m(king)h(or)e(enable)g(alternativ)m(e)i +(options)180 1637 y(and)d(retry)-8 b(.)40 b(It's)26 b(not)h(clear)f(ho) +m(w)g(helpful)d(this)i(w)m(ould)g(b)s(e,)i(in)d(general,)k(since)d +(most)h(searc)m(h)h(sets)g(are)f(rather)180 1761 y(small)j(in)g +(practice.)75 1911 y Fl(\017)60 b Fm(Another)31 b(useful)e(extension)i +(in)m(v)m(olv)m(es)g(mo)s(difying)d(the)k(program)e(to)i(generate)h +(\\minimal")c(p)s(erfect)i(hash)180 2035 y(functions)i(\(under)h +(certain)g(circumstances,)i(the)e(curren)m(t)h(v)m(ersion)f(can)h(b)s +(e)f(rather)g(extra)m(v)-5 b(agan)m(t)37 b(in)d(the)180 +2160 y(generated)i(table)f(size\).)55 b(Again,)36 b(this)e(is)g(mostly) +g(of)h(theoretical)h(in)m(terest,)g(since)f(a)g(sparse)g(table)g(often) +180 2284 y(pro)s(duces)29 b(faster)i(lo)s(okups,)f(and)g(use)g(of)h +(the)g(`)p Fk(-S)p Fm(')f Fk(switch)f Fm(option)h(can)h(minimize)d(the) +j(data)h(size,)e(at)i(the)180 2409 y(exp)s(ense)j(of)g(sligh)m(tly)f +(longer)h(lo)s(okups)f(\(note)j(that)f(the)f(gcc)i(compiler)d +(generally)g(pro)s(duces)g(go)s(o)s(d)i(co)s(de)180 2533 +y(for)30 b Fk(switch)f Fm(statemen)m(ts,)j(reducing)d(the)i(need)f(for) +g(more)g(complex)g(sc)m(hemes\).)75 2683 y Fl(\017)60 +b Fm(In)27 b(addition)f(to)j(impro)m(ving)d(the)i(algorithm,)f(it)h(w)m +(ould)e(also)i(b)s(e)f(useful)f(to)j(generate)g(a)g(C)p +Fk(++)d Fm(class)i(or)g(Ada)180 2807 y(pac)m(k)-5 b(age)32 +b(as)f(the)g(co)s(de)f(output,)g(in)f(addition)g(to)i(the)g(curren)m(t) +f(C)g(routines.)p eop +%%Page: 28 30 +28 29 bop 0 -116 a Fm(28)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Page: 29 31 +29 30 bop 0 -116 a Fm(Chapter)30 b(7:)41 b(Implemen)m(tation)29 +b(Details)i(of)f(GNU)h Fk(gperf)1799 b Fm(29)0 366 y +Fj(7)80 b(Implemen)l(tation)29 b(Details)i(of)f(GNU)h +Fg(gperf)125 740 y Fm(A)42 b(pap)s(er)f(describing)e(the)k(high-lev)m +(el)e(description)f(of)i(the)g(data)h(structures)e(and)h(algorithms)f +(used)g(to)0 865 y(implemen)m(t)c Fk(gperf)f Fm(will)f(so)s(on)j(b)s(e) +f(a)m(v)-5 b(ailable.)63 b(This)36 b(pap)s(er)h(is)g(useful)f(not)i +(only)f(from)h(a)g(main)m(tenance)h(and)0 989 y(enhancemen)m(t)23 +b(p)s(ersp)s(ectiv)m(e,)h(but)e(also)g(b)s(ecause)h(they)f(demonstrate) +h(sev)m(eral)g(clev)m(er)g(and)f(useful)f(programming)0 +1114 y(tec)m(hniques,)31 b(e.g.,)i(`Iteration)f(Num)m(b)s(er')e(b)s(o)s +(olean)g(arra)m(ys,)i(double)e(hashing,)g(a)i(\\safe")g(and)f +(e\016cien)m(t)g(metho)s(d)0 1238 y(for)f(reading)g(arbitrarily)d(long) +j(input)f(from)h(a)g(\014le,)g(and)g(a)h(pro)m(v)-5 b(ably)29 +b(optimal)h(algorithm)f(for)h(sim)m(ultaneously)0 1363 +y(determining)e(b)s(oth)i(the)h(minim)m(um)c(and)j(maxim)m(um)f(elemen) +m(ts)i(in)e(a)i(list.)p eop +%%Page: 30 32 +30 31 bop 0 -116 a Fm(30)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Page: 31 33 +31 32 bop 0 -116 a Fm(Chapter)30 b(8:)41 b(Bibliograph)m(y)2833 +b(31)0 366 y Fj(8)80 b(Bibliograph)l(y)125 808 y Fm([1])27 +b(Chang,)h(C.C.:)38 b Fh(A)27 b(Sc)m(heme)h(for)e(Constructing)g +(Ordered)g(Minimal)e(P)m(erfect)k(Hashing)e(F)-8 b(unctions)31 +b Fm(Infor-)0 932 y(mation)f(Sciences)g(39\(1986\),)k(187-195.)125 +1220 y([2])39 b(Cic)m(helli,)e(Ric)m(hard)h(J.)g Fh(Author's)g(Resp)s +(onse)f(to)i(\\On)f(Cic)m(helli's)e(Minimal)g(P)m(erfect)j(Hash)f(F)-8 +b(unctions)0 1344 y(Metho)s(d")31 b Fm(Comm)m(unications)e(of)h(the)h +(A)m(CM,)g(23,)h(12\(Decem)m(b)s(er)g(1980\),)h(729.)125 +1632 y([3])j(Cic)m(helli,)e(Ric)m(hard)g(J.)h Fh(Minimal)e(P)m(erfect)j +(Hash)f(F)-8 b(unctions)35 b(Made)h(Simple)i Fm(Comm)m(unications)33 +b(of)j(the)0 1756 y(A)m(CM,)31 b(23,)h(1\(Jan)m(uary)e(1980\),)j +(17-19.)125 2044 y([4])45 b(Co)s(ok,)i(C.)d(R.)h(and)e(Oldeho)s(eft,)k +(R.R.)d Fh(A)g(Letter)h(Orien)m(ted)f(Minimal)e(P)m(erfect)j(Hashing)e +(F)-8 b(unction)0 2168 y Fm(SIGPLAN)30 b(Notices,)h(17,)h(9\(Septem)m +(b)s(er)f(1982\),)h(18-27.)125 2456 y([5])43 b(Cormac)m(k,)k(G.)c(V.)g +(and)f(Horsp)s(o)s(ol,)j(R.)e(N.)g(S.)g(and)f(Kaiserw)m(erth,)j(M.)e +Fh(Practical)g(P)m(erfect)h(Hashing)0 2580 y Fm(Computer)30 +b(Journal,)f(28,)i(1\(Jan)m(uary)g(1985\),)i(54-58.)125 +2868 y([6])d(Jaesc)m(hk)m(e,)i(G.)f Fh(Recipro)s(cal)e(Hashing:)40 +b(A)30 b(Metho)s(d)g(for)g(Generating)g(Minimal)e(P)m(erfect)j(Hashing) +f(F)-8 b(unc-)0 2992 y(tions)33 b Fm(Comm)m(unications)c(of)i(the)g(A)m +(CM,)g(24,)g(12\(Decem)m(b)s(er)i(1981\),)f(829-833.)125 +3280 y([7])27 b(Jaesc)m(hk)m(e,)i(G.)e(and)f(Osterburg,)g(G.)h +Fh(On)f(Cic)m(helli's)e(Minimal)g(P)m(erfect)j(Hash)g(F)-8 +b(unctions)26 b(Metho)s(d)k Fm(Com-)0 3404 y(m)m(unications)f(of)i(the) +f(A)m(CM,)h(23,)h(12\(Decem)m(b)s(er)g(1980\),)h(728-729.)125 +3692 y([8])e(Sager,)h(Thomas)e(J.)h Fh(A)g(P)m(olynomial)e(Time)h +(Generator)i(for)e(Minimal)f(P)m(erfect)j(Hash)f(F)-8 +b(unctions)34 b Fm(Com-)0 3816 y(m)m(unications)29 b(of)i(the)f(A)m +(CM,)h(28,)h(5\(Decem)m(b)s(er)g(1985\),)h(523-532)125 +4104 y([9])40 b(Sc)m(hmidt,)i(Douglas)e(C.)g Fh(GPERF:)g(A)g(P)m +(erfect)i(Hash)d(F)-8 b(unction)40 b(Generator)48 b Fm(Second)39 +b(USENIX)h(C)p Fk(++)0 4228 y Fm(Conference)30 b(Pro)s(ceedings,)g +(April)e(1990.)125 4516 y([10])k(Seb)s(esta,)f(R.W.)h(and)e(T)-8 +b(a)m(ylor,)32 b(M.A.)f Fh(Minimal)e(P)m(erfect)j(Hash)f(F)-8 +b(unctions)31 b(for)f(Reserv)m(ed)i(W)-8 b(ord)31 b(Lists)0 +4640 y Fm(SIGPLAN)f(Notices,)h(20,)h(12\(Septem)m(b)s(er)f(1985\),)i +(47-53.)125 4928 y([11])28 b(Sprugnoli,)c(R.)j Fh(P)m(erfect)h(Hashing) +e(F)-8 b(unctions:)39 b(A)27 b(Single)e(Prob)s(e)h(Retrieving)g(Metho)s +(d)g(for)h(Static)g(Sets)0 5053 y Fm(Comm)m(unications)i(of)h(the)h(A)m +(CM,)g(20)g(11\(No)m(v)m(em)m(b)s(er)i(1977\),)g(841-850.)125 +5340 y([12])e(Stallman,)e(Ric)m(hard)h(M.)h Fh(Using)e(and)h(P)m +(orting)g(GNU)h(CC)38 b Fm(F)-8 b(ree)31 b(Soft)m(w)m(are)h(F)-8 +b(oundation,)30 b(1988.)p eop +%%Page: 32 34 +32 33 bop 0 -116 a Fm(32)2920 b(User's)31 b(Guide)e(to)i +Fk(gperf)125 366 y Fm([13])g(Stroustrup,)e(Bjarne)i Fh(The)e(C)p +Fk(++)h Fh(Programming)f(Language.)42 b Fm(Addison-W)-8 +b(esley)g(,)30 b(1986.)125 640 y([14])h(Tiemann,)e(Mic)m(hael)i(D.)g +Fh(User's)f(Guide)f(to)j(GNU)f(C)p Fk(++)e Fm(F)-8 b(ree)32 +b(Soft)m(w)m(are)f(F)-8 b(oundation,)30 b(1989.)p eop +%%Page: -1 35 +-1 34 bop 3875 -116 a Fm(i)0 366 y Fj(T)-13 b(able)31 +b(of)f(Con)l(ten)l(ts)0 715 y Fi(GNU)45 b(GENERAL)g(PUBLIC)g(LICENSE)25 +b Fb(.)19 b(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)69 +b Fi(1)299 871 y Fm(Pream)m(ble)15 b Fa(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)45 +b Fm(1)299 995 y(TERMS)29 b(AND)j(CONDITIONS)15 b Fa(.)f(.)h(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +45 b Fm(2)299 1120 y(App)s(endix:)38 b(Ho)m(w)31 b(to)g(Apply)e(These)h +(T)-8 b(erms)30 b(to)h(Y)-8 b(our)31 b(New)f(Programs)d +Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)56 b Fm(5)0 1369 +y Fi(Con)l(tributors)46 b(to)f(GNU)g Ff(gperf)e Fi(Utilit)l(y)g +Fb(.)19 b(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h +(.)85 b Fi(7)0 1649 y(1)135 b(In)l(tro)t(duction)40 b +Fb(.)20 b(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f +(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.) +f(.)85 b Fi(9)0 1929 y(2)135 b(Static)45 b(searc)l(h)h(structures)f +(and)f(GNU)h Ff(gperf)38 b Fb(.)20 b(.)f(.)g(.)h(.)f(.)h(.)f(.)85 +b Fi(11)0 2210 y(3)135 b(High-Lev)l(el)46 b(Description)g(of)f(GNU)g +Ff(gperf)15 b Fb(.)i(.)i(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)59 +b Fi(13)299 2365 y Fm(3.1)92 b(Input)29 b(F)-8 b(ormat)32 +b(to)f Fk(gperf)22 b Fa(.)16 b(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)53 b Fm(13)598 +2490 y(3.1.1)93 b Fk(struct)28 b Fm(Declarations)j(and)f(C)g(Co)s(de)g +(Inclusion)24 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g +(.)56 b Fm(14)598 2614 y(3.1.2)93 b(F)-8 b(ormat)31 b(for)f(Keyw)m(ord) +g(En)m(tries)16 b Fa(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)45 +b Fm(15)598 2739 y(3.1.3)93 b(Including)27 b(Additional)h(C)i(F)-8 +b(unctions)19 b Fa(.)14 b(.)h(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)48 b Fm(16)299 +2863 y(3.2)92 b(Output)29 b(F)-8 b(ormat)32 b(for)e(Generated)h(C)f(Co) +s(de)g(with)f Fk(gperf)22 b Fa(.)14 b(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)52 b Fm(16)0 3112 y Fi(4)135 b(Options)45 +b(to)g(the)h Ff(gperf)c Fi(Utilit)l(y)24 b Fb(.)e(.)d(.)g(.)h(.)f(.)h +(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)69 +b Fi(19)299 3268 y Fm(4.1)92 b(Options)29 b(that)i(a\013ect)h(In)m +(terpretation)e(of)h(the)f(Input)f(File)d Fa(.)15 b(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)56 b Fm(19)299 3393 y(4.2)92 +b(Options)29 b(to)i(sp)s(ecify)e(the)i(Language)g(for)f(the)h(Output)e +(Co)s(de)13 b Fa(.)h(.)h(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)42 +b Fm(19)299 3517 y(4.3)92 b(Options)29 b(for)h(\014ne)g(tuning)f +(Details)h(in)f(the)i(Output)e(Co)s(de)23 b Fa(.)14 b(.)h(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)52 b Fm(20)299 3642 +y(4.4)92 b(Options)29 b(for)h(c)m(hanging)g(the)h(Algorithms)e(emplo)m +(y)m(ed)h(b)m(y)h Fk(gperf)21 b Fa(.)13 b(.)i(.)g(.)g(.)g(.)g(.)g(.)g +(.)50 b Fm(21)299 3766 y(4.5)92 b(Informativ)m(e)30 b(Output)d +Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)57 b Fm(24)0 4015 +y Fi(5)135 b(Kno)l(wn)45 b(Bugs)f(and)h(Limitations)i(with)e +Ff(gperf)28 b Fb(.)17 b(.)i(.)h(.)f(.)h(.)f(.)h(.)72 +b Fi(25)0 4296 y(6)135 b(Things)44 b(Still)i(Left)g(to)f(Do)17 +b Fb(.)j(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.) +g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)62 b Fi(27)0 4576 y(7)135 +b(Implemen)l(tation)47 b(Details)g(of)e(GNU)g Ff(gperf)30 +b Fb(.)20 b(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)78 b Fi(29)0 +4856 y(8)135 b(Bibliograph)l(y)32 b Fb(.)19 b(.)h(.)f(.)h(.)f(.)g(.)h +(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.) +h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)76 b Fi(31)p eop +%%Page: -2 36 +-2 35 bop 0 -116 a Fm(ii)2958 b(User's)31 b(Guide)e(to)i +Fk(gperf)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/gperf.texi b/doc/gperf.texi new file mode 100644 index 0000000..c4a3575 --- /dev/null +++ b/doc/gperf.texi @@ -0,0 +1,1251 @@ +\input texinfo @c -*-texinfo-*- + +@settitle User's Guide to @code{gperf} +@setfilename gperf.info + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Gperf: (gperf). Perfect Hash Function Generator. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +This file documents the features of the GNU Perfect Hash Function Generator + +Copyright (C) 1989-1998 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through @TeX{} and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided 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 @code{gperf} 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 + +@setchapternewpage odd + +@titlepage +@center @titlefont{User's Guide} +@sp 2 +@center @titlefont{for the} +@sp 2 +@center @titlefont{GNU GPERF Utility} +@sp 4 +@center Douglas C. Schmidt +@sp 3 +@center last updated 14 April 1998 +@sp 1 +@center for version 2.7 +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1989-1998 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 @code{gperf} 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 @code{gperf} 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) +@unnumbered 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. + +@end ifinfo +@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:: Static search structures and GNU 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. +* Implementation:: Implementation Details for GNU GPERF. +* Bibliography:: Material Referenced in this Report. + + --- 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} + +Input Format to @code{gperf} + +* Declarations:: @code{struct} Declarations and C Code Inclusion. +* Keywords:: Format for Keyword Entries. +* Functions:: Including Additional C Functions. + +Options to the @code{gperf} Utility + +* 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 Copying, Contributors, Top, Top +@unnumbered GNU GENERAL PUBLIC LICENSE +@center Version 1, February 1989 + +@display +Copyright @copyright{} 1989 Free Software Foundation, Inc. +675 Mass Ave, Cambridge, MA 02139, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@unnumberedsec Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our 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. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, 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 a 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 tell them 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. + + The precise terms and conditions for copying, distribution and +modification follow. + +@iftex +@unnumberedsec TERMS AND CONDITIONS +@end iftex +@ifinfo +@center TERMS AND CONDITIONS +@end ifinfo + +@enumerate +@item +This License Agreement 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 work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as ``you''. + +@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 +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + +@item +You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + +@itemize @bullet +@item +cause the modified files to carry prominent notices stating that +you changed the files and the date of any change; and + +@item +cause the whole of any work that you distribute or publish, that +in whole or in part contains the Program or any part thereof, either +with or without modifications, to be licensed at no charge to all +third parties under the terms of this General Public License (except +that you may choose to grant warranty protection to some or all +third parties, at your option). + +@item +If the modified program normally reads commands interactively when +run, you must cause it, when started running for such interactive use +in the simplest and most usual 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 General +Public License. + +@item +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. +@end itemize + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + +@item +You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + +@itemize @bullet +@item +accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of +Paragraphs 1 and 2 above; or, + +@item +accompany it with a written offer, valid for at least three +years, to give any third party free (except for a nominal charge +for the cost of distribution) a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of +Paragraphs 1 and 2 above; or, + +@item +accompany it with the information you received as to where the +corresponding source code may be obtained. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form alone.) +@end itemize + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + +@item +You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + +@item +By copying, distributing or modifying 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. + +@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. + +@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 the 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 +the 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 +@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 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 humanity, 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 a brief idea of what it does.} +Copyright (C) 19@var{yy} @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 1, 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) 19@var{yy} @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 `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 a sample; alter the names: + +@example +Yoyodyne, Inc., hereby disclaims all copyright interest in the +program `Gnomovision' (a program to direct compilers to make passes +at assemblers) written by James Hacker. + +@var{signature of Ty Coon}, 1 April 1989 +Ty Coon, President of Vice +@end example + +That's all there is to it! + +@node Contributors, Motivation, Copying, Top +@unnumbered Contributors to GNU @code{gperf} Utility + +@itemize @bullet +@item +The GNU @code{gperf} perfect hash function generator utility was +originally written in GNU C++ by Douglas C. Schmidt. It is now also +available in a highly-portable ``old-style'' C version. 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{} and @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}. +@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 >= n}. If +@var{k = n} 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 Pascal, GNU +Modula 3, and GNU indent. Complete C++ source code for @code{gperf} is +available via anonymous ftp from @code{ics.uci.edu} and +@code{ftp.santafe.edu}. @code{gperf} was also distributed along with +the GNU libg++ library for several years. A highly portable, +functionally equivalent K&R C version of @code{gperf} is archived in +comp.sources.unix, volume 20. Finally, a paper describing +@code{gperf}'s design and implementation in greater detail is available +in the Second USENIX C++ Conference proceedings. + +@node Search Structures, Description, Motivation, Top +@chapter Static search structures and GNU @code{gperf} + +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 @code{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. + + +@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 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} +@end menu + +The perfect hash function generator @code{gperf} reads a set of +``keywords'' from a @dfn{keyfile} (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 characters 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} + +You can control the input keyfile 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}, all sections of @code{gperf}'s input +are optional. The following sections describe the input format for each +section. + +@menu +* Declarations:: @code{struct} Declarations and C Code Inclusion. +* Keywords:: Format for Keyword Entries. +* Functions:: Including Additional C Functions. +@end menu + +@node Declarations, Keywords, Input Format, Input Format +@subsection @code{struct} Declarations and C Code Inclusion + +The keyword input file optionally contains a section for including +arbitrary C declarations and definitions, as well as provisions for +providing a user-supplied @code{struct}. If the @samp{-t} option +@emph{is} enabled, you @emph{must} provide a C @code{struct} as the last +component in the declaration section from the keyfile file. The first +field in this struct must be a @code{char *} identifier called @samp{name}, +although it is possible to modify this field's name with the @samp{-K} +option described below. + +Here is simple example, using months of the year and their attributes as +input: + +@example +@group +struct months @{ 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 + +Separating the @code{struct} declaration from the list of key words and +other fields are a pair of consecutive percent signs, @code{%%}, +appearing left justified in the first column, as in the UNIX utility +@code{lex}. + +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 @code{%@{}, @code{%@}} 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 months *months, int is_leap_year); +%@} +struct months @{ 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 + +It is possible to omit the declaration section entirely. In this case +the keyfile begins directly with the first keyword line, e.g.: + +@example +@group +january, 1, 31, 31 +february, 2, 28, 29 +march, 3, 31, 31 +april, 4, 30, 30 +... +@end group +@end example + +@node Keywords, Functions, Declarations, Input Format +@subsection Format for Keyword Entries + +The second keyfile 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. + +The first field of each non-comment line is always the key itself. It +should be given as a simple name, i.e., without surrounding +string quotation marks, and be left-justified flush against the first +column. 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.@code{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 @code{%%} 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 is @emph{not} enabled +these fields are simply ignored. All previous examples except the last +one contain keyword attributes. + +@node Functions, , 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 @code{%%} 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 Output Format, , Input Format, Description +@section Output Format for Generated C Code with @code{gperf} + +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 the name for +@code{in_word_set} 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: + +@example +@group +static int hash (char *str, int len); +int in_word_set (char *str, int len); +@end group +@end example + +By default, the generated @code{hash} function returns an integer value +created by adding @var{len} to several user-specified @var{str} key +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 +@var{hash_table}; its meaning and properties are described below. +@xref{Implementation}. The relevant key positions are specified via the +@samp{-k} option when running @code{gperf}, as detailed in the @emph{Options} +section below. @xref{Options}. + +Two options, @samp{-g} (assume you are compiling with GNU C and its +@code{inline} feature) and @samp{-a} (assume ANSI C-style function +prototypes), alter the content of both the generated @code{hash} and +@code{in_word_set} routines. However, function @code{in_word_set} may +be modified more extensively, in response to your option settings. The +options that affect the @code{in_word_set} structure are: + +@itemize @bullet +@table @samp +@item -t +Make use of the user-defined @code{struct}. + +@item -S @var{total switch statements} +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 +@end itemize + +If the @samp{-t} and @samp{-S} options are omitted, the +default action is to generate a @code{char *} array containing the keys, +together with additional null 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 Options, Input Details, Description, Top +@chapter Options to the @code{gperf} Utility + +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{-h} option. Here is the complete +list of options. + +@menu +* 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 Input Details, Output Language, Options, Options +@section Options that affect Interpretation of the Input File + +@itemize @bullet +@table @samp +@item -e @var{keyword delimiter list} +Allows the user to provide a string containing delimiters used to +separate keywords from their attributes. The default is ",\n". 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 +Allows you to include a @code{struct} type declaration for generated +code. Any text before a pair of consecutive %% is consider part of the +type declaration. Key words 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, and G++, Pascal, and Modula 2 and 3 +reserved words are distributed with this release. +@end table +@end itemize + +@node Output Language, Output Details, Input Details, Options +@section Options to specify the Language for the Output Code + +@itemize @bullet +@table @samp +@item -L @var{generated language name} +Instructs @code{gperf} to generate code in the language specified by the +option's argument. Languages handled are currently: + +@itemize @bullet +@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 +@end itemize + +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 +@end itemize + +@node Output Details, Algorithmic Details, Output Language, Options +@section Options for fine tuning Details in the Output Code + +@itemize @bullet +@table @samp +@item -K @var{key name} +This option is only useful when option @samp{-t} 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 -H @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} +Allows you to specify the name for the generated lookup function. +Default name is @samp{in_word_set}. This option permits completely automatic +generation of perfect hash functions, especially when multiple generated +hash functions are used in the same application. + +@item -Z @var{class name} +This option is only useful when option @samp{-L C++} has been given. +It allows you to specify the name of generated C++ class. Default name is +@code{Perfect_Hash}. + +@item -7 +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 (characters in the range 0..127). +(Note that the ANSI C functions @code{isalnum} and @code{isgraph} do +@emph{not} guarantee that a character is in this range. Only an explicit +test like @samp{c >= 'A' && c <= 'Z'} guarantees this.) This was the +default in earlier versions of @code{gperf}; now the default is to assume +8-bit characters. + +@item -c +Generates C code that uses the @code{strncmp} function to perform +string comparisons. The default action is to use @code{strcmp}. + +@item -C +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 +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 +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 +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 -W @var{hash table 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} +is given. + +@item -S @var{total switch statements} +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 keyfiles. 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 +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 +@end itemize + +@node Algorithmic Details, Verbosity, Output Details, Options +@section Options for changing the Algorithms employed by @code{gperf} + +@itemize @bullet +@table @samp +@item -k @var{keys} +Allows selection of the character key positions used in the keywords' +hash function. The allowable choices range between 1-126, 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 meta-character '*' causes the generated +hash function to consider @strong{all} character positions in each key, +whereas '$' instructs the hash function to use the ``final character'' +of a key (this is the only way to use a character position greater than +126, 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 +character in each key (which may differ for each key, obviously). Keys +with length less than the indicated key positions work properly, since +selected key positions exceeding the key length are simply not +referenced in the hash function. + +@item -l +Compare key lengths before trying a string comparison. This might cut +down on the number of string comparisons made during the lookup, since +keys 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} is not enabled), since the length table +contains as many elements as there are entries in the lookup table. + +@item -D +Handle keywords whose key position sets hash to duplicate values. +Duplicate hash values occur for two reasons: + +@itemize @bullet +@item +Since @code{gperf} does not backtrack it is possible for it to process +all your input keywords without finding a unique mapping for each word. +However, frequently only a very small number of duplicates occur, and +the majority of keys still require one probe into the table. +@item +Sometimes a set of keys may have the same names, but possess different +attributes. With the -D option @code{gperf} treats all these keys as part of +an equivalence class and generates a perfect hash function with multiple +comparisons for duplicate keys. 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. +@end itemize + +Option @samp{-D} is extremely useful for certain large or highly +redundant keyword sets, e.g., assembler instruction opcodes. +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 -f @var{iteration amount} +Generate the perfect hash function ``fast''. This decreases @code{gperf}'s +running time at the cost of minimizing generated table-size. The +iteration amount represents the number of times to iterate when +resolving a collision. `0' means iterate by the number of keywords. +This option is probably most useful when used in conjunction with options +@samp{-D} and/or @samp{-S} for @emph{large} keyword sets. + +@item -i @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} is used. Also, +@samp{-i} is overriden when the @samp{-r} option is used. + +@item -j @var{jump value} +Affects the ``jump value'', i.e., how far to advance the +associated character 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 +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 -o +Reorders the keywords by sorting the keywords so that frequently +occuring key position set components appear first. A second reordering +pass follows so that keys with ``already determined values'' are placed +towards the front of the keylist. This may decrease the time required +to generate a perfect hash function for many keyword sets, and also +produce more minimal perfect hash functions. The reason for this is +that the reordering helps prune the search time by handling inevitable +collisions early in the search process. On the other hand, if the +number of keywords is @emph{very} large using @samp{-o} may +@emph{increase} @code{gperf}'s execution time, since collisions will begin +earlier and continue throughout the remainder of keyword processing. +See Cichelli's paper from the January 1980 Communications of the ACM for +details. + +@item -r +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. If @code{gperf} has difficultly with a certain keyword set try using +@samp{-r} or @samp{-D}. + +@item -s @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 keys. +If the @var{size-multiple} is negative the maximum associated value is +calculated by @emph{dividing} it into the total number of keys. For +example, 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 -3 means ``allow the maximum associated value to +be about 3 times smaller than the number of input keys''. Negative +values are useful for limiting the overall size of the generated hash +table, though this usually increases the number of duplicate hash +values. + +If `generate switch' option @samp{-S} 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 keys (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. In particular, setting this value too high slows down +@code{gperf}'s runtime, since it must search through a much larger range +of values. Judicious use of the @samp{-f} option helps alleviate this +overhead, however. +@end table +@end itemize + +@node Verbosity, Bugs, Algorithmic Details, Options +@section Informative Output + +@itemize @bullet +@table @samp +@item -h +Prints a short summary on the meaning of each program option. Aborts +further program execution. + +@item -v +Prints out the current version number. + +@item -d +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 +@end itemize + +@node Bugs, Projects, Verbosity, 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. + +However, since @code{gperf} does not backtrack no guaranteed solution +occurs on every run. On the other hand, it is usually easy to obtain a +solution by varying the option parameters. In particular, try the +@samp{-r} option, and also try changing the default arguments to the +@samp{-s} and @samp{-j} options. To @emph{guarantee} a solution, use +the @samp{-D} and @samp{-S} options, although the final results are not +likely to be a @emph{perfect} hash function anymore! Finally, use the +@samp{-f} option if you want @code{gperf} to generate the perfect hash +function @emph{fast}, with less emphasis on making it minimal. + +@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 generated 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 key positions selected for a given key has an +arbitrary limit of 126. 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, Implementation, 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 +Make the algorithm more robust. At present, the program halts with an +error diagnostic if it can't find a direct solution and the @samp{-D} +option is not enabled. A more comprehensive, albeit computationally +expensive, approach would employ backtracking or enable alternative +options and retry. It's not clear how helpful this would be, in +general, since most search sets are rather small in practice. + +@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). +Again, 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 a C++ class or Ada package as the code output, in addition to +the current C routines. +@end itemize + +@node Implementation, Bibliography, Projects, Top +@chapter Implementation Details of GNU @code{gperf} + +A paper describing the high-level description of the data structures and +algorithms used to implement @code{gperf} will soon be available. This +paper is useful not only from a maintenance and enhancement perspective, +but also because they demonstrate several clever and useful programming +techniques, e.g., `Iteration Number' boolean arrays, double +hashing, a ``safe'' and efficient method for reading arbitrarily long +input from a file, and a provably optimal algorithm for simultaneously +determining both the minimum and maximum elements in a list. + +@page + +@node Bibliography, , Implementation, 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] Sebesta, R.W. and Taylor, M.A. @i{Minimal Perfect Hash Functions +for Reserved Word Lists} SIGPLAN Notices, 20, 12(September 1985), 47-53. + +[11] Sprugnoli, R. @i{Perfect Hashing Functions: A Single Probe +Retrieving Method for Static Sets} Communications of the ACM, 20 +11(November 1977), 841-850. + +[12] Stallman, Richard M. @i{Using and Porting GNU CC} Free Software Foundation, +1988. + +[13] Stroustrup, Bjarne @i{The C++ Programming Language.} Addison-Wesley, 1986. + +[14] Tiemann, Michael D. @i{User's Guide to GNU C++} Free Software +Foundation, 1989. + +@contents +@bye diff --git a/doc/gperf_1.html b/doc/gperf_1.html new file mode 100644 index 0000000..89d5807 --- /dev/null +++ b/doc/gperf_1.html @@ -0,0 +1,25 @@ + + + + +User's Guide to gperf - Introduction + + +Go to the first, previous, next, last section, table of contents. +


+ + +

Introduction

+ +

+This manual documents the GNU gperf perfect hash function generator +utility, focusing on its features and how to use them, and how to report +bugs. + +

+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_10.html b/doc/gperf_10.html new file mode 100644 index 0000000..736ce2b --- /dev/null +++ b/doc/gperf_10.html @@ -0,0 +1,30 @@ + + + + +User's Guide to gperf - 7 Implementation Details of GNU gperf + + +Go to the first, previous, next, last section, table of contents. +


+ + +

7 Implementation Details of GNU gperf

+ +

+A paper describing the high-level description of the data structures and +algorithms used to implement gperf will soon be available. This +paper is useful not only from a maintenance and enhancement perspective, +but also because they demonstrate several clever and useful programming +techniques, e.g., `Iteration Number' boolean arrays, double +hashing, a "safe" and efficient method for reading arbitrarily long +input from a file, and a provably optimal algorithm for simultaneously +determining both the minimum and maximum elements in a list. + +

+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_11.html b/doc/gperf_11.html new file mode 100644 index 0000000..a4eeb45 --- /dev/null +++ b/doc/gperf_11.html @@ -0,0 +1,82 @@ + + + + +User's Guide to gperf - 8 Bibliography + + +Go to the first, previous, next, last section, table of contents. +


+ + +

8 Bibliography

+ +

+[1] Chang, C.C.: A Scheme for Constructing Ordered Minimal Perfect +Hashing Functions Information Sciences 39(1986), 187-195. + +[2] Cichelli, Richard J. 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. Minimal Perfect Hash Functions Made Simple +Communications of the ACM, 23, 1(January 1980), 17-19. + +[4] Cook, C. R. and Oldehoeft, R.R. 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. +Practical Perfect Hashing Computer Journal, 28, 1(January 1985), 54-58. + +[6] Jaeschke, G. 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. On Cichelli's Minimal Perfect +Hash Functions Method Communications of the ACM, 23, 12(December 1980), +728-729. + +

+

+[8] Sager, Thomas J. A Polynomial Time Generator for Minimal Perfect +Hash Functions Communications of the ACM, 28, 5(December 1985), 523-532 + +

+

+[9] Schmidt, Douglas C. GPERF: A Perfect Hash Function Generator +Second USENIX C++ Conference Proceedings, April 1990. + +

+

+[10] Sebesta, R.W. and Taylor, M.A. Minimal Perfect Hash Functions +for Reserved Word Lists SIGPLAN Notices, 20, 12(September 1985), 47-53. + +

+

+[11] Sprugnoli, R. Perfect Hashing Functions: A Single Probe +Retrieving Method for Static Sets Communications of the ACM, 20 +11(November 1977), 841-850. + +

+

+[12] Stallman, Richard M. Using and Porting GNU CC Free Software Foundation, +1988. + +

+

+[13] Stroustrup, Bjarne The C++ Programming Language. Addison-Wesley, 1986. + +

+

+[14] Tiemann, Michael D. User's Guide to GNU C++ Free Software +Foundation, 1989. + +

+


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_2.html b/doc/gperf_2.html new file mode 100644 index 0000000..f5d7d5e --- /dev/null +++ b/doc/gperf_2.html @@ -0,0 +1,360 @@ + + + + +User's Guide to gperf - GNU GENERAL PUBLIC LICENSE + + +Go to the first, previous, next, last section, table of contents. +


+ + +

GNU GENERAL PUBLIC LICENSE

+

+Version 1, February 1989 + +

+ +
+Copyright (C) 1989 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+ + + +

Preamble

+ +

+ The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our 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. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + +

+

+ When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, 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 a 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 tell them 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. + +

+

+ The precise terms and conditions for copying, distribution and +modification follow. + +

+

+TERMS AND CONDITIONS + +

+ +
    +
  1. + +This License Agreement 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 work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + +
  2. + +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 +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + +
  3. + +You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + +
      +
    • + +cause the modified files to carry prominent notices stating that +you changed the files and the date of any change; and + +
    • + +cause the whole of any work that you distribute or publish, that +in whole or in part contains the Program or any part thereof, either +with or without modifications, to be licensed at no charge to all +third parties under the terms of this General Public License (except +that you may choose to grant warranty protection to some or all +third parties, at your option). + +
    • + +If the modified program normally reads commands interactively when +run, you must cause it, when started running for such interactive use +in the simplest and most usual 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 General +Public License. + +
    • + +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. +
    + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + +
  4. + +You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + +
      +
    • + +accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of +Paragraphs 1 and 2 above; or, + +
    • + +accompany it with a written offer, valid for at least three +years, to give any third party free (except for a nominal charge +for the cost of distribution) a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of +Paragraphs 1 and 2 above; or, + +
    • + +accompany it with the information you received as to where the +corresponding source code may be obtained. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form alone.) +
    + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + +
  5. + +You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + +
  6. + +By copying, distributing or modifying 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. + +
  7. + +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. + +
  8. + +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 the 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 +the license, you may choose any version ever published by the Free Software +Foundation. + +
  9. + +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 + +
  10. + +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. + +
  11. + +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 humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +

+

+ To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + +

+ +
+one line to give the program's name and a brief idea of what it does.
+Copyright (C) 19yy  name of author
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, 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) 19yy name of author
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+
+ +

+The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +

+

+You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + +

+ +
+Yoyodyne, Inc., hereby disclaims all copyright interest in the
+program `Gnomovision' (a program to direct compilers to make passes
+at assemblers) written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+ +

+That's all there is to it! + +

+


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_3.html b/doc/gperf_3.html new file mode 100644 index 0000000..ab23359 --- /dev/null +++ b/doc/gperf_3.html @@ -0,0 +1,42 @@ + + + + +User's Guide to gperf - Contributors to GNU gperf Utility + + +Go to the first, previous, next, last section, table of contents. +


+ + +

Contributors to GNU gperf Utility

+ + +
    +
  • + +The GNU gperf perfect hash function generator utility was +originally written in GNU C++ by Douglas C. Schmidt. It is now also +available in a highly-portable "old-style" C version. 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 <bug-gnu-utils@gnu.org> and <schmidt@ics.uci.edu>. + +
  • + +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 gperf. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_4.html b/doc/gperf_4.html new file mode 100644 index 0000000..eed515d --- /dev/null +++ b/doc/gperf_4.html @@ -0,0 +1,44 @@ + + + + +User's Guide to gperf - 1 Introduction + + +Go to the first, previous, next, last section, table of contents. +


+ + +

1 Introduction

+ +

+gperf is a perfect hash function generator written in C++. It +transforms an n element user-specified keyword set W into +a perfect hash function F. F uniquely maps keywords in +W onto the range 0..k, where k >= n. If +k = n then F is a minimal perfect hash function. +gperf generates a 0..k element static lookup table and a +pair of C functions. These functions determine whether a given +character string s occurs in W, using at most one probe +into the lookup table. + +

+

+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 Pascal, GNU +Modula 3, and GNU indent. Complete C++ source code for gperf is +available via anonymous ftp from ics.uci.edu and +ftp.santafe.edu. gperf was also distributed along with +the GNU libg++ library for several years. A highly portable, +functionally equivalent K&R C version of gperf is archived in +comp.sources.unix, volume 20. Finally, a paper describing +gperf's design and implementation in greater detail is available +in the Second USENIX C++ Conference proceedings. + +

+


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_5.html b/doc/gperf_5.html new file mode 100644 index 0000000..e231c7f --- /dev/null +++ b/doc/gperf_5.html @@ -0,0 +1,95 @@ + + + + +User's Guide to gperf - 2 Static search structures and GNU gperf + + +Go to the first, previous, next, last section, table of contents. +


+ + +

2 Static search structures and GNU gperf

+ +

+A static search structure is an Abstract Data Type with certain +fundamental operations, e.g., initialize, insert, +and retrieve. Conceptually, all insertions occur before any +retrievals. In practice, gperf generates a 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 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 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 n element +sorted array is space efficient, though the average-case time +complexity for retrieval operations using binary search is +proportional to log 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. + +

+ +

+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: + +

+ +
    +
  • + +It allows keyword recognition in a static search set using at most +one probe into the hash table. This represents the "perfect" +property. +
  • + +The actual memory allocated to store the keywords is precisely large +enough for the keyword set, and no larger. This is the +"minimal" property. +
+ +

+For most applications it is far easier to generate perfect hash +functions than 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. gperf's default +behavior generates near-minimal perfect hash functions for +keyword sets. However, 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 once, if it +subsequently receives heavy use multiple times. 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 gperf is currently +used in several production and research compilers, including GNU C, GNU +C++, GNU Pascal, and GNU Modula 3. The latter two compilers are not yet +part of the official GNU distribution. Each compiler utilizes +gperf to automatically generate static search structures that +efficiently identify their respective reserved keywords. + +

+


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_6.html b/doc/gperf_6.html new file mode 100644 index 0000000..8a51b3b --- /dev/null +++ b/doc/gperf_6.html @@ -0,0 +1,292 @@ + + + + +User's Guide to gperf - 3 High-Level Description of GNU gperf + + +Go to the first, previous, next, last section, table of contents. +


+ + +

3 High-Level Description of GNU gperf

+ +

+The perfect hash function generator gperf reads a set of +"keywords" from a keyfile (or from the standard input by +default). It attempts to derive a perfect hashing function that +recognizes a member of the static keyword set with at most a +single probe into the lookup table. If 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 gperf. + +

+

+By default, 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 gperf to utilize a C switch +statement scheme that minimizes data space storage size. Furthermore, +using a C switch may actually speed up the keyword retrieval time +somewhat. Actual results depend on your C compiler, of course. + +

+

+In general, gperf assigns values to the characters 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 gperf to find and generate a perfect hash function. +Experimentation is the key to getting the most from gperf. + +

+ + +

3.1 Input Format to gperf

+ +

+You can control the input keyfile format by varying certain command-line +arguments, in particular the `-t' option. The input's appearance +is similar to GNU utilities flex and bison (or UNIX +utilities lex and yacc). Here's an outline of the general +format: + +

+ +
+declarations
+%%
+keywords
+%%
+functions
+
+ +

+Unlike flex or bison, all sections of gperf's input +are optional. The following sections describe the input format for each +section. + +

+ + + +

3.1.1 struct Declarations and C Code Inclusion

+ +

+The keyword input file optionally contains a section for including +arbitrary C declarations and definitions, as well as provisions for +providing a user-supplied struct. If the `-t' option +is enabled, you must provide a C struct as the last +component in the declaration section from the keyfile file. The first +field in this struct must be a char * identifier called `name', +although it is possible to modify this field's name with the `-K' +option described below. + +

+

+Here is simple example, using months of the year and their attributes as +input: + +

+ +
+struct months { 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
+
+ +

+Separating the struct declaration from the list of key words and +other fields are a pair of consecutive percent signs, %%, +appearing left justified in the first column, as in the UNIX utility +lex. + +

+

+Using a syntax similar to GNU utilities flex and 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 %{, %} pairs. Here is +an input fragment based on the previous example that illustrates this +feature: + +

+ +
+%{
+#include <assert.h>
+/* This section of code is inserted directly into the output. */
+int return_month_days (struct months *months, int is_leap_year);
+%}
+struct months { char *name; int number; int days; int leap_days; };
+%%
+january,   1, 31, 31
+february,  2, 28, 29
+march,     3, 31, 31
+...
+
+ +

+It is possible to omit the declaration section entirely. In this case +the keyfile begins directly with the first keyword line, e.g.: + +

+ +
+january,   1, 31, 31
+february,  2, 28, 29
+march,     3, 31, 31
+april,     4, 30, 30
+...
+
+ + + +

3.1.2 Format for Keyword Entries

+ +

+The second keyfile format section contains lines of keywords and any +associated attributes you might supply. A line beginning with `#' +in the first column is considered a comment. Everything following the +`#' is ignored, up to and including the following newline. + +

+

+The first field of each non-comment line is always the key itself. It +should be given as a simple name, i.e., without surrounding +string quotation marks, and be left-justified flush against the first +column. 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: + +

+ +
+# 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
+
+ +

+Note that unlike flex or bison the first %% 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 struct provided by you in the +declaration section. If the `-t' option is not enabled +these fields are simply ignored. All previous examples except the last +one contain keyword attributes. + +

+ + +

3.1.3 Including Additional C Functions

+ +

+The optional third section also corresponds closely with conventions +found in flex and bison. All text in this section, +starting at the final %% 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. + +

+ + +

3.2 Output Format for Generated C Code with gperf

+ +

+Several options control how the generated C code appears on the standard +output. Two C function are generated. They are called hash and +in_word_set, although you may modify the name for +in_word_set with a command-line option. Both functions require +two arguments, a string, char * str, and a length +parameter, int len. Their default function prototypes are +as follows: + +

+ +
+static int hash (char *str, int len);
+int in_word_set (char *str, int len);
+
+ +

+By default, the generated hash function returns an integer value +created by adding len to several user-specified str key +positions indexed into an associated values table stored in a +local static array. The associated values table is constructed +internally by gperf and later output as a static local C array called +hash_table; its meaning and properties are described below. +See section 7 Implementation Details of GNU gperf. The relevant key positions are specified via the +`-k' option when running gperf, as detailed in the Options +section below. See section 4 Options to the gperf Utility. + +

+

+Two options, `-g' (assume you are compiling with GNU C and its +inline feature) and `-a' (assume ANSI C-style function +prototypes), alter the content of both the generated hash and +in_word_set routines. However, function in_word_set may +be modified more extensively, in response to your option settings. The +options that affect the in_word_set structure are: + +

+ +
    +
    + +
    `-t' +
    +Make use of the user-defined struct. + +
    `-S total switch statements' +
    +Generate 1 or more C 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. +
    +
+ +

+If the `-t' and `-S' options are omitted, the +default action is to generate a char * array containing the keys, +together with additional null 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. + +

+


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_7.html b/doc/gperf_7.html new file mode 100644 index 0000000..0516c37 --- /dev/null +++ b/doc/gperf_7.html @@ -0,0 +1,393 @@ + + + + +User's Guide to gperf - 4 Options to the gperf Utility + + +Go to the first, previous, next, last section, table of contents. +


+ + +

4 Options to the gperf Utility

+ +

+There are many options to gperf. They were added to make +the program more convenient for use with real applications. "On-line" +help is readily available via the `-h' option. Here is the complete +list of options. + +

+ + + +

4.1 Options that affect Interpretation of the Input File

+ + +
    +
    + +
    `-e keyword delimiter list' +
    +Allows the user to provide a string containing delimiters used to +separate keywords from their attributes. The default is ",\n". 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. + +
    `-t' +
    +Allows you to include a struct type declaration for generated +code. Any text before a pair of consecutive %% is consider part of the +type declaration. Key words 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, and G++, Pascal, and Modula 2 and 3 +reserved words are distributed with this release. +
    +
+ + + +

4.2 Options to specify the Language for the Output Code

+ + +
    +
    + +
    `-L generated language name' +
    +Instructs gperf to generate code in the language specified by the +option's argument. Languages handled are currently: + + +
      +
      + +
      `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 `const'. + +
      `C' +
      +Common C. This language is understood by ANSI C compilers, and also by +old-style C compilers, provided that you #define const to empty +for compilers which don't know about this keyword. + +
      `ANSI-C' +
      +ANSI C. This language is understood by ANSI C compilers and C++ compilers. + +
      `C++' +
      +C++. This language is understood by C++ compilers. +
      +
    + +The default is C. + +
    `-a' +
    +This option is supported for compatibility with previous releases of +gperf. It does not do anything. + +
    `-g' +
    +This option is supported for compatibility with previous releases of +gperf. It does not do anything. +
    +
+ + + +

4.3 Options for fine tuning Details in the Output Code

+ + +
    +
    + +
    `-K key name' +
    +This option is only useful when option `-t' has been given. +By default, the program assumes the structure component identifier for +the keyword is `name'. This option allows an arbitrary choice of +identifier for this component, although it still must occur as the first +field in your supplied struct. + +
    `-H hash function name' +
    +Allows you to specify the name for the generated hash function. Default +name is `hash'. This option permits the use of two hash tables in the +same file. + +
    `-N lookup function name' +
    +Allows you to specify the name for the generated lookup function. +Default name is `in_word_set'. This option permits completely automatic +generation of perfect hash functions, especially when multiple generated +hash functions are used in the same application. + +
    `-Z class name' +
    +This option is only useful when option `-L C++' has been given. +It allows you to specify the name of generated C++ class. Default name is +Perfect_Hash. + +
    `-7' +
    +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 (characters in the range 0..127). +(Note that the ANSI C functions isalnum and isgraph do +not guarantee that a character is in this range. Only an explicit +test like `c >= 'A' && c <= 'Z'' guarantees this.) This was the +default in earlier versions of gperf; now the default is to assume +8-bit characters. + +
    `-c' +
    +Generates C code that uses the strncmp function to perform +string comparisons. The default action is to use strcmp. + +
    `-C' +
    +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. + +
    `-E' +
    +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 <jjc@ai.mit.edu>. + +
    `-I' +
    +Include the necessary system include file, <string.h>, 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. + +
    `-G' +
    +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). + +
    `-W hash table array name' +
    +Allows you to specify the name for the generated array containing the +hash table. Default name is `wordlist'. This option permits the +use of two hash tables in the same file, even when the option `-G' +is given. + +
    `-S total switch statements' +
    +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 argument to this +option 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 +switch, etc. This is useful since many C compilers cannot +correctly generate code for large switch statements. This option +was inspired in part by Keith Bostic's original C program. + +
    `-T' +
    +Prevents the transfer of the type declaration to the output file. Use +this option if the type is already defined elsewhere. + +
    `-p' +
    +This option is supported for compatibility with previous releases of +gperf. It does not do anything. +
    +
+ + + +

4.4 Options for changing the Algorithms employed by gperf

+ + +
    +
    + +
    `-k keys' +
    +Allows selection of the character key positions used in the keywords' +hash function. The allowable choices range between 1-126, inclusive. +The positions are separated by commas, e.g., `-k 9,4,13,14'; +ranges may be used, e.g., `-k 2-7'; and positions may occur +in any order. Furthermore, the meta-character '*' causes the generated +hash function to consider all character positions in each key, +whereas '$' instructs the hash function to use the "final character" +of a key (this is the only way to use a character position greater than +126, incidentally). + +For instance, the option `-k 1,2,4,6-10,'$'' generates a hash +function that considers positions 1,2,4,6,7,8,9,10, plus the last +character in each key (which may differ for each key, obviously). Keys +with length less than the indicated key positions work properly, since +selected key positions exceeding the key length are simply not +referenced in the hash function. + +
    `-l' +
    +Compare key lengths before trying a string comparison. This might cut +down on the number of string comparisons made during the lookup, since +keys with different lengths are never compared via strcmp. +However, using `-l' might greatly increase the size of the +generated C code if the lookup table range is large (which implies that +the switch option `-S' is not enabled), since the length table +contains as many elements as there are entries in the lookup table. + +
    `-D' +
    +Handle keywords whose key position sets hash to duplicate values. +Duplicate hash values occur for two reasons: + + +
      +
    • + +Since gperf does not backtrack it is possible for it to process +all your input keywords without finding a unique mapping for each word. +However, frequently only a very small number of duplicates occur, and +the majority of keys still require one probe into the table. +
    • + +Sometimes a set of keys may have the same names, but possess different +attributes. With the -D option gperf treats all these keys as part of +an equivalence class and generates a perfect hash function with multiple +comparisons for duplicate keys. It is up to you to completely +disambiguate the keywords by modifying the generated C code. However, +gperf helps you out by organizing the output. +
    + +Option `-D' is extremely useful for certain large or highly +redundant keyword sets, e.g., assembler instruction opcodes. +Using this option usually means that the generated hash function is no +longer perfect. On the other hand, it permits gperf to work on +keyword sets that it otherwise could not handle. + +
    `-f iteration amount' +
    +Generate the perfect hash function "fast". This decreases gperf's +running time at the cost of minimizing generated table-size. The +iteration amount represents the number of times to iterate when +resolving a collision. `0' means iterate by the number of keywords. +This option is probably most useful when used in conjunction with options +`-D' and/or `-S' for large keyword sets. + +
    `-i initial value' +
    +Provides an initial 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 `-S' is used. Also, +`-i' is overriden when the `-r' option is used. + +
    `-j jump value' +
    +Affects the "jump value", i.e., how far to advance the +associated character value upon collisions. Jump value is rounded +up to an odd number, the default is 5. If the jump value is 0 +gperf jumps by random amounts. + +
    `-n' +
    +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. + +
    `-o' +
    +Reorders the keywords by sorting the keywords so that frequently +occuring key position set components appear first. A second reordering +pass follows so that keys with "already determined values" are placed +towards the front of the keylist. This may decrease the time required +to generate a perfect hash function for many keyword sets, and also +produce more minimal perfect hash functions. The reason for this is +that the reordering helps prune the search time by handling inevitable +collisions early in the search process. On the other hand, if the +number of keywords is very large using `-o' may +increase gperf's execution time, since collisions will begin +earlier and continue throughout the remainder of keyword processing. +See Cichelli's paper from the January 1980 Communications of the ACM for +details. + +
    `-r' +
    +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. If gperf has difficultly with a certain keyword set try using +`-r' or `-D'. + +
    `-s 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 keys. +If the size-multiple is negative the maximum associated value is +calculated by dividing it into the total number of keys. For +example, 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 -3 means "allow the maximum associated value to +be about 3 times smaller than the number of input keys". Negative +values are useful for limiting the overall size of the generated hash +table, though this usually increases the number of duplicate hash +values. + +If `generate switch' option `-S' is 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 keys (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. In particular, setting this value too high slows down +gperf's runtime, since it must search through a much larger range +of values. Judicious use of the `-f' option helps alleviate this +overhead, however. +
    +
+ + + +

4.5 Informative Output

+ + +
    +
    + +
    `-h' +
    +Prints a short summary on the meaning of each program option. Aborts +further program execution. + +
    `-v' +
    +Prints out the current version number. + +
    `-d' +
    +Enables the debugging option. This produces verbose diagnostics to +"standard error" when 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 `-d' +option is enabled. +
    +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_8.html b/doc/gperf_8.html new file mode 100644 index 0000000..862b5ec --- /dev/null +++ b/doc/gperf_8.html @@ -0,0 +1,66 @@ + + + + +User's Guide to gperf - 5 Known Bugs and Limitations with gperf + + +Go to the first, previous, next, last section, table of contents. +


+ + +

5 Known Bugs and Limitations with gperf

+ +

+The following are some limitations with the current release of +gperf: + +

+ +
    +
  • + +The 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 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. + +However, since gperf does not backtrack no guaranteed solution +occurs on every run. On the other hand, it is usually easy to obtain a +solution by varying the option parameters. In particular, try the +`-r' option, and also try changing the default arguments to the +`-s' and `-j' options. To guarantee a solution, use +the `-D' and `-S' options, although the final results are not +likely to be a perfect hash function anymore! Finally, use the +`-f' option if you want gperf to generate the perfect hash +function fast, with less emphasis on making it minimal. + +
  • + +The size of the generate static keyword array can get 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 greatly inflates the object code size. If this +situation occurs, consider using the `-S' option to reduce data +size, potentially increasing keyword recognition time a negligible +amount. Since many C compilers cannot correctly generated code for +large switch statements it is important to qualify the -S option +with an appropriate numerical argument that controls the number of +switch statements generated. + +
  • + +The maximum number of key positions selected for a given key has an +arbitrary limit of 126. This restriction should be removed, and if +anyone considers this a problem write me and let me know so I can remove +the constraint. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_9.html b/doc/gperf_9.html new file mode 100644 index 0000000..c129729 --- /dev/null +++ b/doc/gperf_9.html @@ -0,0 +1,54 @@ + + + + +User's Guide to gperf - 6 Things Still Left to Do + + +Go to the first, previous, next, last section, table of contents. +


+ + +

6 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: + +

+ +
    +
  • + +Make the algorithm more robust. At present, the program halts with an +error diagnostic if it can't find a direct solution and the `-D' +option is not enabled. A more comprehensive, albeit computationally +expensive, approach would employ backtracking or enable alternative +options and retry. It's not clear how helpful this would be, in +general, since most search sets are rather small in practice. + +
  • + +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). +Again, this is mostly of theoretical interest, since a sparse table +often produces faster lookups, and use of the `-S' switch +option can minimize the data size, at the expense of slightly longer +lookups (note that the gcc compiler generally produces good code for +switch statements, reducing the need for more complex schemes). + +
  • + +In addition to improving the algorithm, it would also be useful to +generate a C++ class or Ada package as the code output, in addition to +the current C routines. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/gperf_toc.html b/doc/gperf_toc.html new file mode 100644 index 0000000..c330262 --- /dev/null +++ b/doc/gperf_toc.html @@ -0,0 +1,50 @@ + + + + +User's Guide to gperf - Table of Contents + + +

User's Guide to gperf

+

+


+

+


+This document was generated on 15 April 1998 using the +texi2html +translator version 1.51.

+ + diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..d9a82c5 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,4585 @@ +%% TeX macros to handle texinfo files + +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, +% 94, 95, 1996 Free Software Foundation, Inc. + +%This texinfo.tex file is free software; you can redistribute it and/or +%modify it under the terms of the GNU General Public License as +%published by the Free Software Foundation; either version 2, or (at +%your option) any later version. + +%This texinfo.tex file is distributed in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%General Public License for more details. + +%You should have received a copy of the GNU General Public License +%along with this texinfo.tex file; see the file COPYING. If not, write +%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +%Boston, MA 02111-1307, USA. + + +%In other words, you are welcome to use, share and improve this program. +%You are forbidden to forbid anyone else to use, share and improve +%what you give them. Help stamp out software-hoarding! + + +% Send bug reports to bug-texinfo@prep.ai.mit.edu. +% Please include a *precise* test case in each bug report. + + +% Make it possible to create a .fmt file just by loading this file: +% if the underlying format is not loaded, start by loading it now. +% Added by gildea November 1993. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi + +% This automatically updates the version number based on RCS. +\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}} +\deftexinfoversion$Revision$ +\message{Loading texinfo package [Version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{} + \catcode`+=\active \catcode`\_=\active} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptextilde=\~ +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexdots=\dots +\let\ptexdot=\. +\let\ptexstar=\* +\let\ptexend=\end +\let\ptexbullet=\bullet +\let\ptexb=\b +\let\ptexc=\c +\let\ptexi=\i +\let\ptext=\t +\let\ptexl=\l +\let\ptexL=\L + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} +\let\~ = \tie % And make it available as @~. + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English. +\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi% +\def\putwordInfo{Info}% +\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi% +\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi% +\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi% +\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi% +\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi% +\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi% +\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi% +\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi% +\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi% + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset \bindingoffset=0pt +\newdimen \normaloffset \normaloffset=\hoffset +\newdimen\pagewidth \newdimen\pageheight +\pagewidth=\hsize \pageheight=\vsize + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% + +%---------------------Begin change----------------------- +% +%%%% For @cropmarks command. +% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\cornerlong \newdimen\cornerthick +\newdimen \topandbottommargin +\newdimen \outerhsize \newdimen \outervsize +\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks +\outerhsize=7in +%\outervsize=9.5in +% Alternative @smallbook page size is 9.25in +\outervsize=9.25in +\topandbottommargin=.75in +% +%---------------------End change----------------------- + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions itself, but you have to call it yourself. +\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}} +\def\onepageout#1{\hoffset=\normaloffset +\ifodd\pageno \advance\hoffset by \bindingoffset +\else \advance\hoffset by -\bindingoffset\fi +{\escapechar=`\\\relax % makes sure backslash is used in output files. +\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}% +{\let\hsize=\pagewidth \makefootline}}}% +\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi} + +%%%% For @cropmarks command %%%% + +% Here is a modification of the main output routine for Near East Publications +% This provides right-angle cropmarks at all four corners. +% The contents of the page are centerlined into the cropmarks, +% and any desired binding offset is added as an \hskip on either +% site of the centerlined box. (P. A. MacKay, 12 November, 1986) +% +\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up +{\escapechar=`\\\relax % makes sure backslash is used in output files. + \shipout + \vbox to \outervsize{\hsize=\outerhsize + \vbox{\line{\ewtop\hfill\ewtop}} + \nointerlineskip + \line{\vbox{\moveleft\cornerthick\nstop} + \hfill + \vbox{\moveright\cornerthick\nstop}} + \vskip \topandbottommargin + \centerline{\ifodd\pageno\hskip\bindingoffset\fi + \vbox{ + {\let\hsize=\pagewidth \makeheadline} + \pagebody{#1} + {\let\hsize=\pagewidth \makefootline}} + \ifodd\pageno\else\hskip\bindingoffset\fi} + \vskip \topandbottommargin plus1fill minus1fill + \boxmaxdepth\cornerthick + \line{\vbox{\moveleft\cornerthick\nsbot} + \hfill + \vbox{\moveright\cornerthick\nsbot}} + \nointerlineskip + \vbox{\line{\ewbot\hfill\ewbot}} + }} + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi} +% +% Do @cropmarks to get crop marks +\def\cropmarks{\let\onepageout=\croppageout } + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment. Type Return to continue.} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Type to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = 12.5pt +\def\singlespace{% + % Why was this kern here? It messes up equalizing space above and below + % environments. --karl, 6may93 + %{\advance \baselineskip by -\singlespaceskip + %\kern \baselineskip}% + \setleading \singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt \char '100}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. + +\def\mylbrace {{\tt \char '173}} +\def\myrbrace {{\tt \char '175}} +\let\{=\mylbrace +\let\}=\myrbrace + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @enddots{} is an end-of-sentence ellipsis. +\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000} + +% @! is an end-of-sentence bang. +\gdef\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\gdef\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000 +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output some dots + +\def\dots{$\ldots$} + +% @page forces the start of a new page + +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. + +\def\inmargin#1{% +\strut\vadjust{\nobreak\kern-\strutdepth + \vtop to \strutdepth{\baselineskip\strutdepth\vss + \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=12 + \catcode`~=12 + \catcode`^=12 + \catcode`_=12 + \catcode`|=12 + \catcode`<=12 + \catcode`>=12 + \catcode`+=12 + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\par \vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other% +\parsearg \commentxxx} + +\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } + +\let\c=\comment + +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% +\let\chapter=\relax +\let\unnumbered=\relax +\let\top=\relax +\let\unnumberedsec=\relax +\let\unnumberedsection=\relax +\let\unnumberedsubsec=\relax +\let\unnumberedsubsection=\relax +\let\unnumberedsubsubsec=\relax +\let\unnumberedsubsubsection=\relax +\let\section=\relax +\let\subsec=\relax +\let\subsubsec=\relax +\let\subsection=\relax +\let\subsubsection=\relax +\let\appendix=\relax +\let\appendixsec=\relax +\let\appendixsection=\relax +\let\appendixsubsec=\relax +\let\appendixsubsection=\relax +\let\appendixsubsubsec=\relax +\let\appendixsubsubsection=\relax +\let\contents=\relax +\let\smallbook=\relax +\let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\everyheading = \relax + \let\evenheading = \relax + \let\oddheading = \relax + \let\everyfooting = \relax + \let\evenfooting = \relax + \let\oddfooting = \relax + \let\headings = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax + \let\item = \relax + \let\message = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\ifhtml{\doignore{ifhtml}} +\def\html{\doignore{html}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. + +\def\dircategory{\comment} + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + \long\def\doignoretext##1\end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % Similarly for index fonts (mostly for their use in + % smallexample) + \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont + \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont + \let\indsf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}} +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +% +\def\value#1{\expandafter + \ifx\csname SET#1\endcsname\relax + {\{No value for ``#1''\}} + \else \csname SET#1\endcsname \fi} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex always succeeds; we read the text following, through @end +% iftex). But `@end iftex' should be valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\defineunmatchedend{iftex} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +\def\donoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\setref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\let\refill=\relax + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \readauxfile + \opencontents + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + \comment % Ignore the actual filename. +} + +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +\def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx} +\def\macroxxx#1#2 \end macro{% +\expandafter\gdef\macrotemp#1{#2}% +\endgroup} + +%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx} +%\def\linemacroxxx#1#2 \end linemacro{% +%\let\parsearg=\relax +%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}% +%\expandafter\xdef\macrotemp{\parsearg\macrotempx}% +%\expandafter\gdef\macrotempx#1{#2}% +%\endgroup} + +%\def\butfirst#1{} + +\message{fonts,} + +% Font-change commands. + +% Texinfo supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +%% Try out Computer Modern fonts at \magstephalf +\let\mainmagstep=\magstephalf + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\setfont\textrm\rmshape{12}{1000} +\setfont\texttt\ttshape{12}{1000} +\else +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples. +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\setfont\ninett\ttshape{9}{1000} +\setfont\indrm\rmshape{9}{1000} +\setfont\indit\slshape{9}{1000} +\let\indsl=\indit +\let\indtt=\ninett +\let\indttsl=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\setfont\indsc\scshape{10}{900} +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for headings +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{12}{\magstep2} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. +% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. +% \setfont\ssecsl\slshape{10}{\magstep1} +% \setfont\ssectt\ttshape{10}{\magstep1} +% \setfont\ssecsf\sfshape{10}{\magstep1} + +%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. +%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than +%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. +%\setfont\ssectt\ttshape{10}{1315} +%\setfont\ssecsf\sfshape{10}{1315} + +%\let\ssecbf=\ssecrm + +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{\magstep1} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled \magstep1 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\let\authorrm = \secrm + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts} +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl + \resetmathfonts} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartitalic +\let\dfn=\smartitalic +\let\emph=\smartitalic +\let\cite=\smartitalic + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp #1{`\tclose{#1}'\null} +\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\samp +\let\url=\samp % perhaps include a hypertex \special eventually + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate an a dash. +% -- rms. +{ +\catcode`\-=\active +\catcode`\_=\active +\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex} +% The following is used by \doprintindex to insure that long function names +% wrap around. It is necessary for - and _ to be active before the index is +% read from the file, as \entry parses the arguments long before \code is +% ever called. -- mycroft +\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder} +} + +\def\realdash{-} +\def\realunder{_} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\normalunderscore\discretionary{}{}{}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. +% +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\ttsl\look}}\fi +\else{\tclose{\ttsl\look}}\fi} + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of +% @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +\def\l#1{{\li #1}\null} % + +\def\r#1{{\rm #1}} % roman font +% Use of \lowercase was suggested. +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\def\titlefont#1{{\titlerm #1}} + +\newif\ifseenauthor +\newif\iffinishedtitlepage + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm +% I deinstalled the following change because \cmr12 is undefined. +% This change was not in the ChangeLog anyway. --rms. +% \let\subtitlerm=\cmr12 + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefont{##1}} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks \evenheadline % Token sequence for heading line of even pages +\newtoks \oddheadline % Token sequence for heading line of odd pages +\newtoks \evenfootline % Token sequence for footing line of even pages +\newtoks \oddfootline % Token sequence for footing line of odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish} +\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish} +\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{\number\day\space +\ifcase\month\or +January\or February\or March\or April\or May\or June\or +July\or August\or September\or October\or November\or December\fi +\space\number\year} + +% Use this if you want the Month Day, Year style of output. +%\def\today{\ifcase\month\or +%January\or February\or March\or April\or May\or June\or +%July\or August\or September\or October\or November\or December\fi +%\space\number\day, \number\year} + +% @settitle line... specifies the title of the document, for headings +% It generates no output of its own + +\def\thistitle{No Title} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + +\message{tables,} + +% @tabs -- simple alignment + +% These don't work. For one thing, \+ is defined as outer. +% So these macros cannot even be defined. + +%\def\tabs{\parsearg\tabszzz} +%\def\tabszzz #1{\settabs\+#1\cr} +%\def\tabline{\parsearg\tablinezzz} +%\def\tablinezzz #1{\+#1\cr} +%\def\&{&} + +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % Be sure we are not still in the middle of a paragraph. + %{\parskip = 0in + %\par + %}% + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. Since that + % text will be indented by \tableindent, we make the item text be in + % a zero-width box. + \noindent + \rlap{\hskip -\tableindent\box0}\ignorespaces% + \endgroup% + \itemxneedsnegativevskiptrue% + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +%% Contains a kludge to get @end[description] to work +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemsize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{\in hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multicolumn or @endmulticolumn do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. + +%%%% +% Dimensions + +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +%%%% +% Macros used to set up halign preamble: +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +%% 2/1/96, to allow fractions to be given with more than one digit. +\def\pickupwholefraction#1 {\global\advance\colcount by1 % +\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}% +\setuptable} + +\newcount\colcount +\def\setuptable#1{\def\firstarg{#1}% +\ifx\firstarg\xendsetuptable\let\go\relax% +\else + \ifx\firstarg\xcolumnfractions\global\setpercenttrue% + \else + \ifsetpercent + \let\go\pickupwholefraction % In this case arg of setuptable + % is the decimal point before the + % number given in percent of hsize. + % We don't need this so we don't use it. + \else + \global\advance\colcount by1 + \setbox0=\hbox{#1}% + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi% + \fi% +\ifx\go\pickupwholefraction\else\let\go\setuptable\fi% +\fi\go} + +%%%% +% multitable syntax +\def\tab{&\hskip1sp\relax} % 2/2/96 + % tiny skip here makes sure this column space is + % maintained, even if it is never used. + + +%%%% +% @multitable ... @end multitable definitions: + +\def\multitable{\parsearg\dotable} + +\def\dotable#1{\bgroup +\let\item\cr +\tolerance=9500 +\hbadness=9500 +\setmultitablespacing +\parskip=\multitableparskip +\parindent=\multitableparindent +\overfullrule=0pt +\global\colcount=0\relax% +\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}% + % To parse everything between @multitable and @item : +\setuptable#1 \endsetuptable + % Need to reset this to 0 after \setuptable. +\global\colcount=0\relax% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. +\halign\bgroup&\global\advance\colcount by 1\relax% +\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % If user has set preamble in terms of percent of \hsize + % we will use that dimension as the width of the column, and + % the \leftskip will keep entries from bumping into each other. + % Table will start at left margin and final column will justify at + % right margin. +\ifnum\colcount=1 +\else + \ifsetpercent + \else + % If user has set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: +\leftskip=\multitablecolspace +\fi +\noindent##}\cr% + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. +\global\everycr{\noalign{% +\filbreak%% keeps underfull box messages off when table breaks over pages. +\global\colcount=0\relax}} +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\setbox0=\vbox{Xy} +\ifdim\multitablelinespace=0pt +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\gdef\multistrut{\vrule height\ht0 depth\dp0 width0pt\relax} +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\else +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. + +\def\newindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +\def\synindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +% Take care of the plain tex accent commands. +\def\"{\realbackslash "}% +\def\`{\realbackslash `}% +\def\'{\realbackslash '}% +\def\^{\realbackslash ^}% +\def\~{\realbackslash ~}% +\def\={\realbackslash =}% +\def\b{\realbackslash b}% +\def\c{\realbackslash c}% +\def\d{\realbackslash d}% +\def\u{\realbackslash u}% +\def\v{\realbackslash v}% +\def\H{\realbackslash H}% +% Take care of the plain tex special European modified letters. +\def\oe{\realbackslash oe}% +\def\ae{\realbackslash ae}% +\def\aa{\realbackslash aa}% +\def\OE{\realbackslash OE}% +\def\AE{\realbackslash AE}% +\def\AA{\realbackslash AA}% +\def\o{\realbackslash o}% +\def\O{\realbackslash O}% +\def\l{\realbackslash l}% +\def\L{\realbackslash L}% +\def\ss{\realbackslash ss}% +% Take care of texinfo commands likely to appear in an index entry. +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\char{\realbackslash char}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\copyright{\realbackslash copyright }% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\t##1{\realbackslash r {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +\unsepspaces +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +% Just ignore accents. +\let\"=\indexdummyfont +\let\`=\indexdummyfont +\let\'=\indexdummyfont +\let\^=\indexdummyfont +\let\~=\indexdummyfont +\let\==\indexdummyfont +\let\b=\indexdummyfont +\let\c=\indexdummyfont +\let\d=\indexdummyfont +\let\u=\indexdummyfont +\let\v=\indexdummyfont +\let\H=\indexdummyfont +% Take care of the plain tex special European modified letters. +\def\oe{oe}% +\def\ae{ae}% +\def\aa{aa}% +\def\OE{OE}% +\def\AE{AE}% +\def\AA{AA}% +\def\o{o}% +\def\O{O}% +\def\l{l}% +\def\L{L}% +\def\ss{ss}% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other +@gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. + +\let\SETmarginindex=\relax %initialize! +% workhorse for all \fooindexes +% #1 is name of index, #2 is stuff to put there +\def\doind #1#2{% +% Put the index entry in the margin if desired. +\ifx\SETmarginindex\relax\else% +\insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% +\fi% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% Expand all macros now EXCEPT \folio +\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now +% so it will be output as is; and it will print as backslash in the indx. +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}}}% +\temp }% +}\penalty\count10}} + +\def\dosubind #1#2#3{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% +\def\rawbackslashxx{\indexbackslash}% +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2 #3}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}{#3}}}% +\temp }% +}\penalty\count10}} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% This is what you call to cause a particular index to get printed. +% Write +% @unnumbered Function Index +% @printindex fn + +\def\printindex{\parsearg\doprintindex} + +\def\doprintindex#1{% + \tex + \dobreak \chapheadingskip {10000} + \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other + \catcode`\$=\other + \catcode`\~=\other + \indexbreaks + % + % The following don't help, since the chars were translated + % when the raw index was written, and their fonts were discarded + % due to \indexnofonts. + %\catcode`\"=\active + %\catcode`\^=\active + %\catcode`\_=\active + %\catcode`\|=\active + %\catcode`\<=\active + %\catcode`\>=\active + % % + \def\indexbackslash{\rawbackslashxx} + \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt + \begindoublecolumns + % + % See if the index file exists and is nonempty. + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + (Index is nonexistent) + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + (Index is empty) + \else + \input \jobname.#1s + \fi + \fi + \closein 1 + \enddoublecolumns + \Etex +} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +% Same as \bigskipamount except no shrink. +% \balancecolumns gets confused if there is any shrink. +\newskip\initialskipamount \initialskipamount 12pt plus4pt + +\def\initial #1{% +{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +\ifdim\lastskip<\initialskipamount +\removelastskip \penalty-200 \vskip \initialskipamount\fi +\line{\secbf#1\hfill}\kern 2pt\penalty10000}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry #1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent=2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ #2% The page number ends the paragraph. + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +%% Define two-column mode, which is used in indexes. +%% Adapted from the TeXbook, page 416. +\catcode `\@=11 + +\newbox\partialpage + +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup + % Grab any single-column material above us. + \output = {\global\setbox\partialpage + =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% + \eject + % + % Now switch to the double-column output routine. + \output={\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it once. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +- < + % 1pt) as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize + \doublecolumnpagegoal +} + +\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage} + +\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage + \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1} + \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3} + \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi + \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi +} +\def\doublecolumnpagegoal{% + \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@ +} +\def\pagesofar{\unvbox\partialpage % + \hsize=\doublecolumnhsize % have to restore this since output routine + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}} +\def\doublecolumnout{% + \setbox5=\copy255 + {\vbadness=10000 \doublecolumnsplit} + \ifvbox255 + \setbox0=\vtop to\dimen@{\unvbox0} + \setbox2=\vtop to\dimen@{\unvbox2} + \onepageout\pagesofar \unvbox255 \penalty\outputpenalty + \else + \setbox0=\vbox{\unvbox5} + \ifvbox0 + \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip + \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth + {\vbadness=10000 + \loop \global\setbox5=\copy0 + \setbox1=\vsplit5 to\dimen@ + \setbox3=\vsplit5 to\dimen@ + \ifvbox5 \global\advance\dimen@ by1pt \repeat + \setbox0=\vbox to\dimen@{\unvbox1} + \setbox2=\vbox to\dimen@{\unvbox3} + \global\setbox\partialpage=\vbox{\pagesofar} + \doublecolumnpagegoal + } + \fi + \fi +} + +\catcode `\@=\other +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount \chapno +\newcount \secno \secno=0 +\newcount \subsecno \subsecno=0 +\newcount \subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount \appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +\newwrite \contentsfile +% This is called from \setfilename. +\def\opencontents{\openout \contentsfile = \jobname.toc} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise + +\def\thischapter{} \def\thissection{} +\def\seccheck#1{\if \pageno<0 % +\errmessage{@#1 not allowed after generating table of contents}\fi +% +} + +\def\chapternofonts{% +\let\rawbackslash=\relax% +\let\frenchspacing=\relax% +\def\result{\realbackslash result} +\def\equiv{\realbackslash equiv} +\def\expansion{\realbackslash expansion} +\def\print{\realbackslash print} +\def\TeX{\realbackslash TeX} +\def\dots{\realbackslash dots} +\def\copyright{\realbackslash copyright} +\def\tt{\realbackslash tt} +\def\bf{\realbackslash bf } +\def\w{\realbackslash w} +\def\less{\realbackslash less} +\def\gtr{\realbackslash gtr} +\def\hat{\realbackslash hat} +\def\char{\realbackslash char} +\def\tclose##1{\realbackslash tclose {##1}} +\def\code##1{\realbackslash code {##1}} +\def\samp##1{\realbackslash samp {##1}} +\def\r##1{\realbackslash r {##1}} +\def\b##1{\realbackslash b {##1}} +\def\key##1{\realbackslash key {##1}} +\def\file##1{\realbackslash file {##1}} +\def\kbd##1{\realbackslash kbd {##1}} +% These are redefined because @smartitalic wouldn't work inside xdef. +\def\i##1{\realbackslash i {##1}} +\def\cite##1{\realbackslash cite {##1}} +\def\var##1{\realbackslash var {##1}} +\def\emph##1{\realbackslash emph {##1}} +\def\dfn##1{\realbackslash dfn {##1}} +} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + + +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{\seccheck{chapter}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{\seccheck{appendix}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 \message{Appendix \appendixletter}% +\chapmacro {#1}{\putwordAppendix{} \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry + {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +\outer\def\top{\parsearg\unnumberedyyy} +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{\seccheck{unnumbered}% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the to achieve this: TeX expands \the only once, +% simply yielding the contents of the . +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +}} + +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{\seccheck{section}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{\seccheck{appendixsection}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{\seccheck{subsection}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry % + {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} + {\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry{#1}% + {\appendixletter} + {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and +% such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\heading{\parsearg\secheadingi} + +\def\subheading{\parsearg\subsecheadingi} + +\def\subsubheading{\parsearg\subsubsecheadingi} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{ +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +\def\chfplain #1#2{% + \pchapsepmacro + {% + \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #2\enspace #1}% + }% + \bigskip + \penalty5000 +} + +\def\unnchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\centerchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + {\rm #1}\hfill}}\bigskip \par\penalty 10000 % +} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 % +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + +% Parameter controlling skip before section headings. + +\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} + +\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Section fonts are the base font at magstep2, which produces +% a size a bit more than 14 points in the default situation. + +\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} +\def\plainsecheading #1{\secheadingi {#1}} +\def\secheadingi #1{{\advance \secheadingskip by \parskip % +\secheadingbreak}% +{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + +% Subsection fonts are the base font at magstep1, +% which produces a size of 12 points. + +\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}} +\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + +\def\subsubsecfonts{\subsecfonts} % Maybe this should change: + % Perhaps make sssec fonts scaled + % magstep half +\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}} +\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} + + +\message{toc printing,} + +% Finish up the main text and prepare to read what we've written +% to \contentsfile. + +\newskip\contentsrightmargin \contentsrightmargin=1in +\def\startcontents#1{% + \pagealignmacro + \immediate\closeout \contentsfile + \ifnum \pageno>0 + \pageno = -1 % Request roman numbered pages. + \fi + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. +} + + +% Normal (long) toc. +\outer\def\contents{% + \startcontents{\putwordTableofContents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{\putwordShortContents}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \endgroup + \vfill \eject +} +\let\shortcontents = \summarycontents + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm \putwordAppendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in in \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we would want to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +% +% \turnoffactive is for the sake of @" used for umlauts. +\def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{\turnoffactive #1}{\turnoffactive #2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +\let\ptexequiv = \equiv + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +\def\point{$\star$} + +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} + +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup +\catcode `\\=0 \catcode `\{=1 \catcode `\}=2 +\catcode `\$=3 \catcode `\&=4 \catcode `\#=6 +\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie +\catcode `\%=14 +\catcode 43=12 +\catcode`\"=12 +\catcode`\==12 +\catcode`\|=12 +\catcode`\<=12 +\catcode`\>=12 +\escapechar=`\\ +% +\let\~=\ptextilde +\let\{=\ptexlbrace +\let\}=\ptexrbrace +\let\.=\ptexdot +\let\*=\ptexstar +\let\dots=\ptexdots +\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}} +\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi} +\def\@{@}% +\let\bullet=\ptexbullet +\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl +\let\L=\ptexL +% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \cartouche: draw rectangle w/rounded corners around argument +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% To ending an @example-like environment, we first end the paragraph +% (via \afterenvbreak's vertical glue), and then the group. That way we +% keep the zero \parskip that the environments set -- \parskip glue +% will be inserted at the beginning of the next paragraph in the +% document, after the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup}% + +% This macro is +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \rawbackslash % have \ input char produce \ char from current font + \gobble +} + +% Define the \E... control sequence only if we are inside the +% environment, so the error checking in \end will work. +% +% We must call \lisp last in the definition, since it reads the +% return following the @example (or whatever) command. +% +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp. This is not used unless the @smallbook +% command is given. Originally contributed by Pavel@xerox. +% +\def\smalllispx{\begingroup + \nonfillstart + \let\Esmalllisp = \nonfillfinish + \let\Esmallexample = \nonfillfinish + % + % Smaller interline space and fonts for small examples. + \setleading{10pt}% + \indexfonts \tt + \rawbackslash % make \ output the \ character from the current font (tt) + \gobble +} + +% This is @display; same as @lisp except use roman font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% This is @format; same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @flushleft (same as @format) and @flushright. +% +\def\flushleft{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushleft = \nonfillfinish + \gobble +} +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \singlespace + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested % +\global\advance\parencount by 1 } +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. +% also in that case restore the outer-level definition of (. +\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi +\global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\dimen3=\rightskip +\advance\dimen3 by -\defbodyindent +\noindent % +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 % +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 +\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +\def\defmethparsebody #1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does, putting the result in \tptemp. +% +\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}% + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + \removeemptybraces#2\relax + #1{\tptemp}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0 +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Function}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$$$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$$$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Macro}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Special Form}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}} + +% @defmethod, and so on + +% @defop {Funny Method} foo-class frobnicate argument + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype{} on #1}% +\defunargs {#3}\endgroup % +} + +% @defmethod == @defop Method + +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} + +\def\defmethodheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% entry in function index +\begingroup\defname {#2}{Method on #1}% +\defunargs {#3}\endgroup % +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype{} of #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{Instance Variable of #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{Variable}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{User Option}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name. +\def\deftypevarheader #1#2{% +\doind {vr}{\code{#2}}% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}% +\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + +\message{cross reference,} +% Define cross-reference macros +\newwrite \auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% \setref{foo} defines a cross-reference point named foo. + +\def\setref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ysectionnumberandtype}} + +\def\unnumbsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ynothing}} + +\def\appendixsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Yappendixletterandtype}} + +% \xref, \pxref, and \ref generate cross-references to specified points. +% For \xrefX, #1 is the node name, #2 the name of the Info +% cross-reference, #3 the printed node name, #4 the name of the Info +% file, #5 the name of the printed manual. All but the node name can be +% omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1>0pt% + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' in \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive \refx{#1-snt}{}}% + \space [\printednodename],\space + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \turnoffactive so that punctuation chars such as underscore +% work in node names. +\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat% +\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}% +\next}} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + $\langle$un\-de\-fined$\rangle$% + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% Read the last existing aux file, if any. No error if none exists. + +% This is the macro invoked by entries in the aux file. +\def\xrdef #1#2{ +{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}} + +\def\readauxfile{% +\begingroup +\catcode `\^^@=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\^^C=\other +\catcode `\^^D=\other +\catcode `\^^E=\other +\catcode `\^^F=\other +\catcode `\^^G=\other +\catcode `\^^H=\other +\catcode `\ =\other +\catcode `\^^L=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode 26=\other +\catcode `\^^[=\other +\catcode `\^^\=\other +\catcode `\^^]=\other +\catcode `\^^^=\other +\catcode `\^^_=\other +\catcode `\@=\other +\catcode `\^=\other +\catcode `\~=\other +\catcode `\[=\other +\catcode `\]=\other +\catcode`\"=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode `\$=\other +\catcode `\#=\other +\catcode `\&=\other +% `\+ does not work, so use 43. +\catcode 43=\other +% Make the characters 128-255 be printing characters +{% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% +}% +% the aux file uses ' as the escape. +% Turn off \ as an escape so we do not lose on +% entries which were dumped with control sequences in their names. +% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ +% Reference to such entries still does not work the way one would wish, +% but at least they do not bomb out when the aux file is read in. +\catcode `\{=1 \catcode `\}=2 +\catcode `\%=\other +\catcode `\'=0 +\catcode`\^=7 % to make ^^e4 etc usable in xref tags +\catcode `\\=\other +\openin 1 \jobname.aux +\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue +\global\warnedobstrue +\fi +% Open the new aux file. Tex will close it automatically at exit. +\openout \auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only.. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +\long\gdef\footnotezzz#1{\insert\footins{% + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + #1\strut}% +} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + + +% End of control word definitions. + +\message{and turning on texinfo input format.} + +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% Set some numeric style parameters, for 8.5 x 11 format. + +%\hsize = 6.5in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 18pt plus 1pt +\setleading{15pt} +\advance\topskip by 1.2cm + +% Prevent underfull vbox error messages. +\vbadness=10000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. This makes it come to about 9pt for the 8.5x11 format. +% +\ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% +\else + \emergencystretch = \hsize + \divide\emergencystretch by 45 +\fi + +% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) +\def\smallbook{ + +% These values for secheadingskip and subsecheadingskip are +% experiments. RJC 7 Aug 1992 +\global\secheadingskip = 17pt plus 6pt minus 3pt +\global\subsecheadingskip = 14pt plus 6pt minus 3pt + +\global\lispnarrowing = 0.3in +\setleading{12pt} +\advance\topskip by -1cm +\global\parskip 3pt plus 1pt +\global\hsize = 5in +\global\vsize=7.5in +\global\tolerance=700 +\global\hfuzz=1pt +\global\contentsrightmargin=0pt +\global\deftypemargin=0pt +\global\defbodyindent=.5cm + +\global\pagewidth=\hsize +\global\pageheight=\vsize + +\global\let\smalllisp=\smalllispx +\global\let\smallexample=\smalllispx +\global\def\Esmallexample{\Esmalllisp} +} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{ +\global\tolerance=700 +\global\hfuzz=1pt +\setleading{12pt} +\global\parskip 15pt plus 1pt + +\global\vsize= 53\baselineskip +\advance\vsize by \topskip +%\global\hsize= 5.85in % A4 wide 10pt +\global\hsize= 6.5in +\global\outerhsize=\hsize +\global\advance\outerhsize by 0.5in +\global\outervsize=\vsize +\global\advance\outervsize by 0.6in + +\global\pagewidth=\hsize +\global\pageheight=\vsize +} + +% Allow control of the text dimensions. Parameters in order: textheight; +% textwidth; voffset; hoffset; binding offset; topskip. +% All require a dimension; +% header is additional; added length extends the bottom of the page. + +\def\changepagesizes#1#2#3#4#5#6{ + \global\vsize= #1 + \global\topskip= #6 + \advance\vsize by \topskip + \global\voffset= #3 + \global\hsize= #2 + \global\outerhsize=\hsize + \global\advance\outerhsize by 0.5in + \global\outervsize=\vsize + \global\advance\outervsize by 0.6in + \global\pagewidth=\hsize + \global\pageheight=\vsize + \global\normaloffset= #4 + \global\bindingoffset= #5} + +% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin +% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +\def\afourlatex + {\global\tolerance=700 + \global\hfuzz=1pt + \setleading{12pt} + \global\parskip 15pt plus 1pt + \advance\baselineskip by 1.6pt + \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm} + } + +% Use @afourwide to print on European A4 paper in wide format. +\def\afourwide{\afourpaper +\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt \char '042}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt \char '176}} +\chardef\hat=`\^ +\catcode`\^=\active +\def\auxhat{\def^{'hat}} +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +\catcode`\|=\active +\def|{{\tt \char '174}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{@let"=@normaldoublequote +@let\=@realbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active @catcode`@_=@active} + +%% These look ok in all fonts, so just make them not special. The @rm below +%% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c page-delimiter: "^\\\\message" +@c End: diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..3b1ee9d --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,109 @@ +# Makefile for gperf/lib + +# Copyright (C) 1989, 1992, 1993, 1998 Free Software Foundation, Inc. +# written by Douglas C. Schmidt (schmidt@ics.uci.edu) +# +# 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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +# Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ + +# Directories used by "make install": +prefix = @prefix@ +local_prefix = /usr/local +exec_prefix = @exec_prefix@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +# Other +AR = ar +AR_FLAGS = rc +RANLIB = @RANLIB@ +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +# Programs used by "make install": +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +VPATH = $(srcdir) + +OBJECTS = getopt.o getopt1.o hash.o +CPPFLAGS = -I$(srcdir) + +TARGETLIB = libgp.a + +all : $(TARGETLIB) + +$(TARGETLIB): $(OBJECTS) + $(RM) $@ + $(AR) $(AR_FLAGS) $@ $(OBJECTS) + $(RANLIB) $@ + +# Don't use implicit rules, since AIX "make" and OSF/1 "make" don't always +# expand $< correctly in this context. +# +#%.o : %.c +# $(CC) $(CFLAGS) $(CPPFLAGS) -c $< +# +#%.o : %.cc +# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< + +getopt.o : getopt.c getopt.h + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/getopt.c + +getopt1.o : getopt1.c getopt.h + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/getopt1.c + +hash.o : hash.cc hash.h + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/hash.cc + +install : all + +installdirs : + +uninstall : + +check : all + +mostlyclean : clean + +clean : force + $(RM) *~ *.s *.o *.a $(TARGETLIB) core + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + +force : diff --git a/lib/configure b/lib/configure new file mode 100755 index 0000000..791b6f8 --- /dev/null +++ b/lib/configure @@ -0,0 +1,1303 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=hash.cc + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:523: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:552: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:581: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:629: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:663: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:668: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:692: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:720: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:741: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:758: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + for ac_prog in $CCC c++ g++ gcc CC cxx cc++ +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:785: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:816: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:856: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:861: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes + ac_test_CXXFLAGS="${CXXFLAGS+set}" + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS= + echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:885: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 + if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" + elif test $ac_cv_prog_cxx_g = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-O2" + fi +else + GXX= + test "${CXXFLAGS+set}" = set || CXXFLAGS="-g" +fi + + echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 +echo "configure:913: checking how to run the C++ preprocessor" >&5 +if test -z "$CXXCPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + CXXCPP="${CXX-g++} -E" + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:931: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CXXCPP=/lib/cpp +fi +rm -f conftest* + ac_cv_prog_CXXCPP="$CXXCPP" +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross +fi +fi +CXXCPP="$ac_cv_prog_CXXCPP" +echo "$ac_t""$CXXCPP" 1>&6 + + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:958: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB="true" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:995: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'cl_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&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 + ac_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 "$ac_t""$INSTALL" 1>&6 +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='$(INSTALL)' +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi + + trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@CXX@%$CXX%g +s%@CXXCPP@%$CXXCPP%g +s%@RANLIB@%$RANLIB%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/lib/configure.in b/lib/configure.in new file mode 100644 index 0000000..98266a1 --- /dev/null +++ b/lib/configure.in @@ -0,0 +1,43 @@ +dnl autoconf configuration for gperf/lib + +dnl Copyright (C) 1998 Free Software Foundation, Inc. +dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu) +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the +dnl Free Software Foundation, 59 Temple Place - Suite 330, Boston, +dnl MA 02111-1307, USA. + +AC_INIT(hash.cc) +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_RANLIB + dnl sets variable RANLIB +CL_PROG_INSTALL + dnl sets variables INSTALL, INSTALL_DATA, INSTALL_PROGRAM +dnl +dnl That's it. +dnl +AC_OUTPUT(Makefile) diff --git a/lib/getopt.c b/lib/getopt.c new file mode 100644 index 0000000..2341d04 --- /dev/null +++ b/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/lib/getopt.c.patch b/lib/getopt.c.patch new file mode 100644 index 0000000..6fedd84 --- /dev/null +++ b/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/lib/getopt.h b/lib/getopt.h new file mode 100644 index 0000000..5be6319 --- /dev/null +++ b/lib/getopt.h @@ -0,0 +1,138 @@ +/* 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 + 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__ + 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/lib/getopt.h.patch b/lib/getopt.h.patch new file mode 100644 index 0000000..7a7c2f1 --- /dev/null +++ b/lib/getopt.h.patch @@ -0,0 +1,40 @@ +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 Thu Apr 16 00:17:42 1998 +*************** +*** 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/lib/getopt1.c b/lib/getopt1.c new file mode 100644 index 0000000..3d264f2 --- /dev/null +++ b/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/lib/hash.cc b/lib/hash.cc new file mode 100644 index 0000000..72a287f --- /dev/null +++ b/lib/hash.cc @@ -0,0 +1,36 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library is distributed in the hope +that it will be useful, but WITHOUT ANY WARRANTY; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +/* + some useful hash functions +*/ + +unsigned int hashpjw (const char* x) // From Dragon book, p436 +{ + unsigned int h = 0; + unsigned int g; + + while (*x != 0) + { + h = (h << 4) + (unsigned char) *x++; + if ((g = h & 0xf0000000) != 0) + h = (h ^ (g >> 24)) ^ g; + } + return h; +} diff --git a/lib/hash.h b/lib/hash.h new file mode 100644 index 0000000..a5f324b --- /dev/null +++ b/lib/hash.h @@ -0,0 +1,27 @@ +// This may look like C code, but it is really -*- C++ -*- + +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library is distributed in the hope +that it will be useful, but WITHOUT ANY WARRANTY; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _hash_h +#define _hash_h 1 + +/* a hash function for null-terminated char* strings using the + method described in Aho, Sethi, & Ullman, p 436. */ +extern unsigned int hashpjw (const char*); + +#endif diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..ec1e682 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,143 @@ +# Makefile for gperf/src + +# Copyright (C) 1989, 1992, 1993, 1998 Free Software Foundation, Inc. +# written by Douglas C. Schmidt (schmidt@ics.uci.edu) +# +# 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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +# Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ + +# Directories used by "make install": +prefix = @prefix@ +local_prefix = /usr/local +exec_prefix = @exec_prefix@ +bindir = @bindir@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +# Other +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +# Programs used by "make install": +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +VPATH = $(srcdir) + +OBJECTS = new.o options.o iterator.o main.o gen-perf.o key-list.o list-node.o \ + hash-table.o bool-array.o read-line.o trace.o vectors.o version.o +LIBS = ../lib/libgp.a -lm +CPPFLAGS = -I. -I$(srcdir)/../lib + +TARGETPROG = gperf + +all : $(TARGETPROG) + +$(TARGETPROG): $(OBJECTS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS) + +# Don't use implicit rules, since AIX "make" and OSF/1 "make" don't always +# expand $< correctly in this context. +# +#%.o : %.c +# $(CC) $(CFLAGS) $(CPPFLAGS) -c $< +# +#%.o : %.cc +# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< + +# Dependencies. +CONFIG_H = config.h +VERSION_H = version.h +VECTORS_H = vectors.h +TRACE_H = trace.h +READ_LINE_H = read-line.h read-line.icc $(TRACE_H) +OPTIONS_H = options.h options.icc $(TRACE_H) +LIST_NODE_H = list-node.h $(VECTORS_H) +KEY_LIST_H = key-list.h $(LIST_NODE_H) $(VECTORS_H) $(READ_LINE_H) +ITERATOR_H = iterator.h +HASH_TABLE_H = hash-table.h $(LIST_NODE_H) +BOOL_ARRAY_H = bool-array.h bool-array.icc $(TRACE_H) $(OPTIONS_H) +GEN_PERF_H = gen-perf.h $(KEY_LIST_H) $(BOOL_ARRAY_H) + +bool-array.o : bool-array.cc $(BOOL_ARRAY_H) $(OPTIONS_H) $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/bool-array.cc +gen-perf.o : gen-perf.cc $(GEN_PERF_H) $(OPTIONS_H) $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/gen-perf.cc +hash-table.o : hash-table.cc $(HASH_TABLE_H) $(OPTIONS_H) $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/hash-table.cc +iterator.o : iterator.cc $(ITERATOR_H) $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/iterator.cc +key-list.o : key-list.cc $(KEY_LIST_H) $(OPTIONS_H) $(READ_LINE_H) $(HASH_TABLE_H) $(TRACE_H) $(VERSION_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/key-list.cc +list-node.o : list-node.cc $(LIST_NODE_H) $(OPTIONS_H) $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/list-node.cc +main.o : main.cc $(OPTIONS_H) $(GEN_PERF_H) $(TRACE_H) $(CONFIG_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/main.cc +new.o : new.cc $(TRACE_H) $(CONFIG_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/new.cc +options.o : options.cc $(OPTIONS_H) $(ITERATOR_H) $(TRACE_H) $(VECTORS_H) $(VERSION_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/options.cc +read-line.o : read-line.cc $(READ_LINE_H) $(OPTIONS_H) $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/read-line.cc +trace.o : trace.cc $(TRACE_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/trace.cc +vectors.o : vectors.cc $(VECTORS_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/vectors.cc +version.o : version.cc $(VERSION_H) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/version.cc + +install : all force + if [ ! -d $(bindir) ] ; then mkdir $(bindir) ; fi + $(INSTALL_PROGRAM) $(TARGETPROG) $(bindir)/$(TARGETPROG) + +installdirs : force + if [ ! -d $(bindir) ] ; then mkdir $(bindir) ; fi + +uninstall : force + $(RM) $(bindir)/$(TARGETPROG) + +check : all + +mostlyclean : clean + +clean : force + $(RM) *~ *.s *.o *.a $(TARGETPROG) core + +distclean : clean + $(RM) config.status config.log config.cache Makefile config.h + +maintainer-clean : distclean + +force : diff --git a/src/bool-array.cc b/src/bool-array.cc new file mode 100644 index 0000000..0774b2d --- /dev/null +++ b/src/bool-array.cc @@ -0,0 +1,49 @@ +/* Fast lookup table abstraction implemented as an Iteration Number Array + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "bool-array.h" + +#include +#include +#include "options.h" +#include "trace.h" + +STORAGE_TYPE * Bool_Array::storage_array; +STORAGE_TYPE Bool_Array::iteration_number; +unsigned int Bool_Array::size; + +/* Prints out debugging diagnostics. */ + +Bool_Array::~Bool_Array (void) +{ + T (Trace t ("Bool_Array::~Bool_Array");) + if (option[DEBUG]) + fprintf (stderr, "\ndumping boolean array information\n" + "size = %d\niteration number = %d\nend of array dump\n", + size, iteration_number); +} + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "bool-array.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/src/bool-array.h b/src/bool-array.h new file mode 100644 index 0000000..8330fcd --- /dev/null +++ b/src/bool-array.h @@ -0,0 +1,66 @@ +/* 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 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Define and implement a simple boolean array abstraction, + uses an Iteration Numbering implementation to save on initialization time. */ + +#ifndef bool_array_h +#define bool_array_h 1 + +#include "trace.h" + +#ifdef LO_CAL +/* If we are on a memory diet then we'll only make these use a limited + amount of storage space. */ +typedef unsigned short STORAGE_TYPE; +#else +typedef unsigned int STORAGE_TYPE; +#endif + +class Bool_Array +{ +private: + static STORAGE_TYPE *storage_array; /* Initialization of the index space. */ + static STORAGE_TYPE iteration_number; /* Keep track of the current iteration. */ + static unsigned int size; /* Keep track of array size. */ + +public: + Bool_Array (void); + ~Bool_Array (void); + static void init (STORAGE_TYPE *buffer, unsigned int s); + static int find (int hash_value); + static void reset (void); +}; + +#ifdef __OPTIMIZE__ /* efficiency hack! */ + +#include +#include +#include "options.h" +#define INLINE inline +#include "bool-array.icc" +#undef INLINE + +#endif + +#endif diff --git a/src/bool-array.icc b/src/bool-array.icc new file mode 100644 index 0000000..6de6f23 --- /dev/null +++ b/src/bool-array.icc @@ -0,0 +1,85 @@ +/* Inline Functions for bool-array.{h,cc}. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +// This needs: +//#include +//#include +//#include "options.h" +//#include "trace.h" + +INLINE +Bool_Array::Bool_Array (void) +{ + T (Trace t ("Bool_Array::Bool_Array");) + storage_array = 0; + iteration_number = size = 0; +} + +INLINE void +Bool_Array::init (STORAGE_TYPE *buffer, unsigned int s) +{ + T (Trace t ("Bool_Array::init");) + size = s; + iteration_number = 1; + storage_array = buffer; + memset (storage_array, 0, s * sizeof (*storage_array)); + if (option[DEBUG]) + fprintf (stderr, "\nbool array size = %d, total bytes = %d\n", + size, (unsigned int) (size * sizeof (*storage_array))); +} + +INLINE int +Bool_Array::find (int index) +{ + T (Trace t ("Bool_Array::find");) + if (storage_array[index] == iteration_number) + return 1; + else + { + storage_array[index] = iteration_number; + return 0; + } +} + +INLINE void +Bool_Array::reset (void) +{ + T (Trace t ("Bool_Array::reset");) + /* If we wrap around it's time to zero things out again! However, this only + occurs once about every 2^31 or 2^15 iterations, so it should probably + never happen! */ + + if (++iteration_number == 0) + { + if (option[DEBUG]) + { + fprintf (stderr, "(re-initializing bool_array)..."); + fflush (stderr); + } + iteration_number = 1; + memset (storage_array, 0, size * sizeof (*storage_array)); + if (option[DEBUG]) + { + fprintf (stderr, "done\n"); + fflush (stderr); + } + } +} diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..4d3d762 --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,19 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if the C++ compiler supports "throw ()" declarations. */ +#undef HAVE_THROW_DECL + +/* Define if you have the getrlimit function. */ +#undef HAVE_GETRLIMIT + +/* Define if you have the setrlimit function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H diff --git a/src/configure b/src/configure new file mode 100755 index 0000000..d3d1091 --- /dev/null +++ b/src/configure @@ -0,0 +1,1573 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=gen-perf.cc + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:524: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:553: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:582: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:630: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:664: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:669: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:693: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:721: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:742: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:759: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + for ac_prog in $CCC c++ g++ gcc CC cxx cc++ +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:786: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:817: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:857: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:862: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes + ac_test_CXXFLAGS="${CXXFLAGS+set}" + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS= + echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:886: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 + if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" + elif test $ac_cv_prog_cxx_g = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-O2" + fi +else + GXX= + test "${CXXFLAGS+set}" = set || CXXFLAGS="-g" +fi + + echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 +echo "configure:914: checking how to run the C++ preprocessor" >&5 +if test -z "$CXXCPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + CXXCPP="${CXX-g++} -E" + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:932: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CXXCPP=/lib/cpp +fi +rm -f conftest* + ac_cv_prog_CXXCPP="$CXXCPP" +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross +fi +fi +CXXCPP="$ac_cv_prog_CXXCPP" +echo "$ac_t""$CXXCPP" 1>&6 + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:967: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'cl_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&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 + ac_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 "$ac_t""$INSTALL" 1>&6 +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='$(INSTALL)' +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi + + echo $ac_n "checking for working throw()""... $ac_c" 1>&6 +echo "configure:1020: checking for working throw()" >&5 +if eval "test \"`echo '$''{'gp_cxx_throw_decl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext < +void operator delete (void* ptr) throw() {} +int main() { + +; return 0; } +EOF +if { (eval echo configure:1042: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gp_cxx_throw_decl=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gp_cxx_throw_decl=no +fi +rm -f conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + + +fi + +echo "$ac_t""$gp_cxx_throw_decl" 1>&6 +if test $gp_cxx_throw_decl = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_THROW_DECL 1 +EOF + +fi +for ac_hdr in unistd.h sys/time.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1073: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1083: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + if test $ac_cv_header_sys_resource_h = yes; then +for ac_func in getrlimit +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1113: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + if test $ac_cv_func_getrlimit = yes; then +for ac_func in setrlimit +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1169: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1197: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + fi +fi +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@CXX@%$CXX%g +s%@CXXCPP@%$CXXCPP%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/src/configure.in b/src/configure.in new file mode 100644 index 0000000..68d267c --- /dev/null +++ b/src/configure.in @@ -0,0 +1,71 @@ +dnl autoconf configuration for gperf/src + +dnl Copyright (C) 1998 Free Software Foundation, Inc. +dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu) +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the +dnl Free Software Foundation, 59 Temple Place - Suite 330, Boston, +dnl MA 02111-1307, USA. + +AC_INIT(gen-perf.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 working throw()]) +AC_CACHE_VAL(gp_cxx_throw_decl,[ +AC_LANG_SAVE() +AC_LANG_CPLUSPLUS() +AC_TRY_COMPILE([#include +void operator delete (void* ptr) throw() {}], [], +gp_cxx_throw_decl=yes, gp_cxx_throw_decl=no) +AC_LANG_RESTORE() +]) +AC_MSG_RESULT([$]gp_cxx_throw_decl) +if test [$]gp_cxx_throw_decl = yes; then + AC_DEFINE(HAVE_THROW_DECL) +fi +dnl +dnl checks for functions and declarations +dnl +AC_CHECK_HEADERS(unistd.h sys/time.h sys/resource.h) + dnl DEFs HAVE_UNISTD_H, HAVE_SYS_TIME_H, HAVE_SYS_RESOURCE_H +if test $ac_cv_header_sys_resource_h = yes; then +AC_CHECK_FUNCS(getrlimit) + dnl DEFS HAVE_GETRLIMIT +if test $ac_cv_func_getrlimit = yes; then +AC_CHECK_FUNCS(setrlimit) + dnl DEFS HAVE_SETRLIMIT +fi +fi +dnl +dnl That's it. +dnl +AC_OUTPUT(Makefile) diff --git a/src/gen-perf.cc b/src/gen-perf.cc new file mode 100644 index 0000000..0d0ad41 --- /dev/null +++ b/src/gen-perf.cc @@ -0,0 +1,342 @@ +/* Provides high-level routines to manipulate the keywork list + structures the code generation output. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include +#include /* declares rand(), srand() */ +#include /* declares time() */ +#include "options.h" +#include "gen-perf.h" +#include "trace.h" + +/* Efficiently returns the least power of two greater than or equal to X! */ +#define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X))) + +/* Reads input keys, possibly applies the reordering heuristic, sets the + maximum associated value size (rounded up to the nearest power of 2), + may initialize the associated values array, and determines the maximum + hash table size. Note: using the random numbers is often helpful, + though not as deterministic, of course! */ + +Gen_Perf::Gen_Perf (void) +{ + T (Trace t ("Gen_Perf::Gen_Perf");) + int asso_value_max; + int non_linked_length; + + Key_List::read_keys (); + if (option[ORDER]) + reorder (); + asso_value_max = option.get_asso_max (); + non_linked_length = Key_List::keyword_list_length (); + num_done = 1; + fewest_collisions = 0; + if (asso_value_max == 0) + asso_value_max = non_linked_length; + else if (asso_value_max > 0) + asso_value_max *= non_linked_length; + else /* if (asso_value_max < 0) */ + asso_value_max = non_linked_length / -asso_value_max; + option.set_asso_max (POW (asso_value_max)); + + if (option[RANDOM]) + { + srand ((long) time (0)); + + for (int i = 0; i < ALPHA_SIZE; i++) + asso_values[i] = (rand () & asso_value_max - 1); + } + else + { + int asso_value = option.initial_value (); + + if (asso_value) /* Initialize array if user requests non-zero default. */ + for (int i = ALPHA_SIZE - 1; i >= 0; i--) + asso_values[i] = asso_value & option.get_asso_max () - 1; + } + max_hash_value = Key_List::max_key_length () + option.get_asso_max () * + option.get_max_keysig_size (); + + 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); +} + +/* Merge two disjoint hash key multisets to form the ordered disjoint union of the sets. + (In a multiset, an element can occur multiple times). + Precondition: both set_1 and set_2 must be ordered. Returns the length + of the combined set. */ + +inline int +Gen_Perf::compute_disjoint_union (const char *set_1, const char *set_2, char *set_3) +{ + T (Trace t ("Gen_Perf::compute_disjoint_union");) + char *base = set_3; + + while (*set_1 && *set_2) + if (*set_1 == *set_2) + set_1++, set_2++; + else + { + *set_3 = *set_1 < *set_2 ? *set_1++ : *set_2++; + if (set_3 == base || *set_3 != *(set_3-1)) set_3++; + } + + while (*set_1) + { + *set_3 = *set_1++; + if (set_3 == base || *set_3 != *(set_3-1)) set_3++; + } + + while (*set_2) + { + *set_3 = *set_2++; + if (set_3 == base || *set_3 != *(set_3-1)) set_3++; + } + *set_3 = '\0'; + return set_3 - base; +} + +/* Sort the UNION_SET in increasing frequency of occurrence. + This speeds up later processing since we may assume the resulting + set (Set_3, in this case), is ordered. Uses insertion sort, since + the UNION_SET is typically short. */ + +inline void +Gen_Perf::sort_set (char *union_set, int len) +{ + T (Trace t ("Gen_Perf::sort_set");) + int i, j; + + for (i = 0, j = len - 1; i < j; i++) + { + int curr; + char tmp; + + for (curr = i + 1, tmp = union_set[curr]; + curr > 0 && occurrences[(unsigned char)tmp] < occurrences[(unsigned char)(union_set[curr-1])]; + curr--) + union_set[curr] = union_set[curr - 1]; + + union_set[curr] = tmp; + } +} + +/* Generate a key set's hash value. */ + +inline int +Gen_Perf::hash (List_Node *key_node) +{ + T (Trace t ("Gen_Perf::hash");) + int sum = option[NOLENGTH] ? 0 : key_node->length; + + for (const char *ptr = key_node->char_set; *ptr; ptr++) + sum += asso_values[(unsigned char)(*ptr)]; + + return key_node->hash_value = sum; +} + +/* Find out how character value change affects successfully hashed items. + Returns FALSE if no other hash values are affected, else returns TRUE. + Note that because Option.Get_Asso_Max is a power of two we can guarantee + that all legal Asso_Values are visited without repetition since + Option.Get_Jump was forced to be an odd value! */ + +inline int +Gen_Perf::affects_prev (char c, List_Node *curr) +{ + T (Trace t ("Gen_Perf::affects_prev");) + int original_char = asso_values[(unsigned char)c]; + int total_iterations = !option[FAST] + ? option.get_asso_max () : option.get_iterations () ? option.get_iterations () : keyword_list_length (); + + /* Try all legal associated values. */ + + for (int i = total_iterations - 1; i >= 0; i--) + { + int collisions = 0; + + asso_values[(unsigned char)c] = + (asso_values[(unsigned char)c] + (option.get_jump () ? option.get_jump () : rand ())) + & (option.get_asso_max () - 1); + + /* Iteration Number array is a win, O(1) intialization time! */ + reset (); + + /* See how this asso_value change affects previous keywords. If + it does better than before we'll take it! */ + + for (List_Node *ptr = head; + !Bool_Array::find (hash (ptr)) || ++collisions < fewest_collisions; + ptr = ptr->next) + if (ptr == curr) + { + fewest_collisions = collisions; + if (option[DEBUG]) + fprintf (stderr, "- resolved after %d iterations", total_iterations - i); + return 0; + } + } + + /* Restore original values, no more tries. */ + asso_values[(unsigned char)c] = original_char; + /* If we're this far it's time to try the next character.... */ + return 1; +} + +/* Change a character value, try least-used characters first. */ + +void +Gen_Perf::change (List_Node *prior, List_Node *curr) +{ + T (Trace t ("Gen_Perf::change");) + static char *union_set; + + if (!union_set) + union_set = new char [2 * option.get_max_keysig_size () + 1]; + + if (option[DEBUG]) + { + fprintf (stderr, "collision on keyword #%d, prior = \"%s\", curr = \"%s\" hash = %d\n", + num_done, prior->key, curr->key, curr->hash_value); + fflush (stderr); + } + sort_set (union_set, compute_disjoint_union (prior->char_set, curr->char_set, union_set)); + + /* Try changing some values, if change doesn't alter other values continue normal action. */ + fewest_collisions++; + + for (char *temp = union_set; *temp; temp++) + if (!affects_prev (*temp, curr)) + { + if (option[DEBUG]) + { + fprintf (stderr, " by changing asso_value['%c'] (char #%d) to %d\n", + *temp, temp - union_set + 1, asso_values[(unsigned char)(*temp)]); + fflush (stderr); + } + return; /* Good, doesn't affect previous hash values, we'll take it. */ + } + + for (List_Node *ptr = head; ptr != curr; ptr = ptr->next) + hash (ptr); + + hash (curr); + + if (option[DEBUG]) + { + fprintf (stderr, "** collision not resolved after %d iterations, %d duplicates remain, continuing...\n", + !option[FAST] ? option.get_asso_max () : option.get_iterations () ? option.get_iterations () : keyword_list_length (), + fewest_collisions + total_duplicates); + fflush (stderr); + } +} + +/* Does the hard stuff.... + Initializes the Iteration Number array, and attempts to find a perfect + function that will hash all the key words without getting any + duplications. This is made much easier since we aren't attempting + to generate *minimum* functions, only perfect ones. + If we can't generate a perfect function in one pass *and* the user + hasn't enabled the DUP option, we'll inform the user to try the + randomization option, use -D, or choose alternative key positions. + The alternatives (e.g., back-tracking) are too time-consuming, i.e, + exponential in the number of keys. */ + +int +Gen_Perf::operator() (void) +{ + T (Trace t ("Gen_Perf::operator()");) +#if LARGE_STACK_ARRAYS + STORAGE_TYPE buffer[max_hash_value + 1]; +#else + // Note: we don't use new, because that invokes a custom operator new. + STORAGE_TYPE *buffer + = (STORAGE_TYPE*) malloc (sizeof(STORAGE_TYPE) * (max_hash_value + 1)); + if (buffer == NULL) + abort (); +#endif + + Bool_Array::init (buffer, max_hash_value + 1); + + List_Node *curr; + for (curr = head; curr; curr = curr->next) + { + hash (curr); + + for (List_Node *ptr = head; ptr != curr; ptr = ptr->next) + if (ptr->hash_value == curr->hash_value) + { + change (ptr, curr); + break; + } + num_done++; + } + + /* Make one final check, just to make sure nothing weird happened.... */ + + Bool_Array::reset (); + + for (curr = head; curr; curr = curr->next) + if (Bool_Array::find (hash (curr))) + if (option[DUP]) /* Keep track of this number... */ + total_duplicates++; + else /* Yow, big problems. we're outta here! */ + { + fprintf (stderr, "\nInternal error, duplicate value %d:\n" + "try options -D or -r, or use new key positions.\n\n", hash (curr)); +#if !LARGE_STACK_ARRAYS + free ((char *) buffer); +#endif + return 1; + } + + /* Sorts the key word list by hash value, and then outputs the list. + The generated hash table code is only output if the early stage of + processing turned out O.K. */ + + sort (); + output (); +#if !LARGE_STACK_ARRAYS + free ((char *) buffer); +#endif + return 0; +} + +/* Prints out some diagnostics upon completion. */ + +Gen_Perf::~Gen_Perf (void) +{ + T (Trace t ("Gen_Perf::~Gen_Perf");) + if (option[DEBUG]) + { + fprintf (stderr, "\ndumping occurrence and associated values tables\n"); + + for (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"); + + } +} + diff --git a/src/gen-perf.h b/src/gen-perf.h new file mode 100644 index 0000000..09b8727 --- /dev/null +++ b/src/gen-perf.h @@ -0,0 +1,50 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Provides high-level routines to manipulate the keyword list + structures the code generation output. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef gen_perf_h +#define gen_perf_h 1 + +#include "key-list.h" +#include "bool-array.h" + +class Gen_Perf : private Key_List, private Bool_Array +{ +private: + int max_hash_value; /* Maximum possible hash value. */ + int fewest_collisions; /* Records fewest # of collisions for asso value. */ + int num_done; /* Number of keywords processed without a collision. */ + + void change (List_Node *prior, List_Node *curr); + int affects_prev (char c, List_Node *curr); + static int hash (List_Node *key_node); + static int compute_disjoint_union (const char *set_1, const char *set_2, char *set_3); + static void sort_set (char *union_set, int len); + +public: + Gen_Perf (void); + ~Gen_Perf (void); + int operator () (void); +}; + +#endif diff --git a/src/hash-table.cc b/src/hash-table.cc new file mode 100644 index 0000000..db8d6dd --- /dev/null +++ b/src/hash-table.cc @@ -0,0 +1,91 @@ +/* Hash table for checking keyword links. Implemented using double hashing. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "hash-table.h" + +#include +#include /* declares memset(), strcmp() */ +#include +#include "options.h" +#include "trace.h" + +#define NIL(TYPE) (TYPE *)0 + +/* The size of the hash table is always the smallest power of 2 >= the size + indicated by the user. This allows several optimizations, including + the use of double hashing and elimination of the mod instruction. + Note that the size had better be larger than the number of items + in the hash table, else there's trouble!!! Note that the memory + for the hash table is allocated *outside* the intialization routine. + This compromises information hiding somewhat, but greatly reduces + memory fragmentation, since we can now use alloca! */ + +Hash_Table::Hash_Table (List_Node **table_ptr, int s): + table (table_ptr), size (s), collisions (0) +{ + T (Trace t ("Hash_Table::Hash_Table");) + memset ((char *) table, 0, size * sizeof (*table)); +} + +Hash_Table::~Hash_Table (void) +{ + T (Trace t ("Hash_Table::~Hash_Table");) + if (option[DEBUG]) + { + int field_width = option.get_max_keysig_size (); + + 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 * (int) sizeof (*table), collisions, + field_width, "keysig"); + + for (int i = size - 1; i >= 0; i--) + if (table[i]) + fprintf (stderr, "%8d, %*s, %s\n", + i, field_width, table[i]->char_set, table[i]->key); + + fprintf (stderr, "\nend dumping hash table\n\n"); + } +} + +/* If the ITEM is already in the hash table return the item found + in the table. Otherwise inserts the ITEM, and returns FALSE. + Uses double hashing. */ + +List_Node * +Hash_Table::operator() (List_Node *item, int ignore_length) +{ + T (Trace t ("Hash_Table::operator()");) + unsigned hash_val = hashpjw (item->char_set); + int probe = hash_val & size - 1; + int increment = (hash_val ^ item->length | 1) & size - 1; + + while (table[probe] + && (strcmp (table[probe]->char_set, item->char_set) + || (!ignore_length && table[probe]->length != item->length))) + { + collisions++; + probe = probe + increment & size - 1; + } + + return table[probe] ? table[probe] : (table[probe] = item, NIL (List_Node)); +} diff --git a/src/hash-table.h b/src/hash-table.h new file mode 100644 index 0000000..7d23999 --- /dev/null +++ b/src/hash-table.h @@ -0,0 +1,42 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Hash table used to check for duplicate keyword entries. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef hash_table_h +#define hash_table_h 1 + +#include "list-node.h" + +class Hash_Table +{ +private: + List_Node **table; /* Vector of pointers to linked lists of List_Node's. */ + int size; /* Size of the vector. */ + int collisions; /* Find out how well our double hashing is working! */ + +public: + Hash_Table (List_Node **t, int s); + ~Hash_Table (void); + List_Node *operator () (List_Node *item, int ignore_length); +}; + +#endif diff --git a/src/iterator.cc b/src/iterator.cc new file mode 100644 index 0000000..dd9d27e --- /dev/null +++ b/src/iterator.cc @@ -0,0 +1,88 @@ +/* Provides an Iterator for keyword characters. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "iterator.h" + +#include +#include +#include "trace.h" + +/* Constructor for Iterator. */ + +Iterator::Iterator (const char *s, int lo, int hi, int word_end, int bad_val, int key_end) +{ + T (Trace t ("Iterator::Iterator");) + end = key_end; + error_value = bad_val; + end_word = word_end; + str = s; + hi_bound = hi; + lo_bound = lo; +} + +/* Provide an Iterator, returning the ``next'' value from + the list of valid values given in the constructor. */ + +int +Iterator::operator() (void) +{ + T (Trace t ("Iterator::operator()");) +/* Variables to record the Iterator's status when handling ranges, e.g., 3-12. */ + + static int size; + static int curr_value; + static int upper_bound; + + if (size) + { + if (++curr_value >= upper_bound) + size = 0; + return curr_value; + } + else + { + while (*str) + switch (*str) + { + default: return error_value; + case ',': str++; break; + case '$': str++; return end_word; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + for (curr_value = 0; isdigit ((unsigned char)(*str)); str++) + curr_value = curr_value * 10 + (*str - '0'); + + if (*str == '-') + { + + for (size = 1, upper_bound = 0; + isdigit ((unsigned char)(*++str)); + upper_bound = upper_bound * 10 + (*str - '0')); + + if (upper_bound <= curr_value || upper_bound > hi_bound) + return error_value; + } + return curr_value >= lo_bound && curr_value <= hi_bound + ? curr_value : error_value; + } + + return end; + } +} diff --git a/src/iterator.h b/src/iterator.h new file mode 100644 index 0000000..d5138ab --- /dev/null +++ b/src/iterator.h @@ -0,0 +1,51 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Provides an Iterator for keyword characters. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Provides an Iterator that expands and decodes a control string containing digits + and ranges, returning an integer every time the generator function is called. + This is used to decode the user's key position requests. For example: + "-k 1,2,5-10,$" will return 1, 2, 5, 6, 7, 8, 9, 10, and 0 ( representing + the abstract ``last character of the key'' on successive calls to the + member function operator (). + No errors are handled in these routines, they are passed back to the + calling routines via a user-supplied Error_Value */ + +#ifndef iterator_h +#define iterator_h 1 + +class Iterator +{ +private: + const char *str; /* A pointer to the string provided by the user. */ + int end; /* Value returned after last key is processed. */ + int end_word; /* A value marking the abstract ``end of word'' ( usually '$'). */ + int error_value; /* Error value returned when input is syntactically erroneous. */ + int hi_bound; /* Greatest possible value, inclusive. */ + int lo_bound; /* Smallest possible value, inclusive. */ + +public: + Iterator (const char *s, int lo, int hi, int word_end, int bad_val, int key_end); + int operator () (void); +}; + +#endif diff --git a/src/key-list.cc b/src/key-list.cc new file mode 100644 index 0000000..38341f3 --- /dev/null +++ b/src/key-list.cc @@ -0,0 +1,1957 @@ +/* Routines for building, ordering, and printing the keyword list. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include +#include /* declares strncpy(), strchr() */ +#include /* declares malloc(), free(), abs(), exit(), abort() */ +#include /* defines assert() */ +#include /* defines SCHAR_MAX etc. */ +#include "options.h" +#include "read-line.h" +#include "hash-table.h" +#include "key-list.h" +#include "trace.h" +#include "version.h" + +/* Make the hash table 8 times larger than the number of keyword entries. */ +static const int TABLE_MULTIPLE = 10; + +/* Efficiently returns the least power of two greater than or equal to X! */ +#define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X))) + +int Key_List::determined[MAX_ALPHA_SIZE]; + +/* Destructor dumps diagnostics during debugging. */ + +Key_List::~Key_List (void) +{ + T (Trace t ("Key_List::~Key_List");) + if (option[DEBUG]) + { + 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); + dump (); + fprintf (stderr, "End dumping list.\n\n"); + } +} + +/* Gathers the input stream into a buffer until one of two things occur: + + 1. We read a '%' followed by a '%' + 2. We read a '%' followed by a '}' + + The first symbolizes the beginning of the keyword list proper, + The second symbolizes the end of the C source code to be generated + verbatim in the output file. + + I assume that the keys are separated from the optional preceding struct + declaration by a consecutive % followed by either % or } starting in + the first column. The code below uses an expandible buffer to scan off + and return a pointer to all the code (if any) appearing before the delimiter. */ + +const char * +Key_List::get_special_input (char delimiter) +{ + T (Trace t ("Key_List::get_special_input");) + int size = 80; + char *buf = new char[size]; + int c, i; + + for (i = 0; (c = getchar ()) != EOF; i++) + { + if (c == '%') + { + if ((c = getchar ()) == delimiter) + { + + while ((c = getchar ()) != '\n') + ; /* discard newline */ + + if (i == 0) + return ""; + else + { + buf[delimiter == '%' && buf[i - 2] == ';' ? i - 2 : i - 1] = '\0'; + return buf; + } + } + else + buf[i++] = '%'; + } + else if (i >= size) /* Yikes, time to grow the buffer! */ + { + char *temp = new char[size *= 2]; + int j; + + for (j = 0; j < i; j++) + temp[j] = buf[j]; + + buf = temp; + } + buf[i] = c; + } + + return 0; /* Problem here. */ +} + +/* Stores any C text that must be included verbatim into the + generated code output. */ + +const char * +Key_List::save_include_src (void) +{ + T (Trace t ("Key_List::save_include_src");) + int c; + + if ((c = getchar ()) != '%') + ungetc (c, stdin); + else if ((c = getchar ()) != '{') + { + fprintf (stderr, "internal error, %c != '{' on line %d in file %s", c, __LINE__, __FILE__); + exit (1); + } + else + return get_special_input ('}'); + return ""; +} + +/* Determines from the input file whether the user wants to build a table + from a user-defined struct, or whether the user is content to simply + use the default array of keys. */ + +const char * +Key_List::get_array_type (void) +{ + T (Trace t ("Key_List::get_array_type");) + return get_special_input ('%'); +} + +/* strcspn - find length of initial segment of S consisting entirely + of characters not from REJECT (borrowed from Henry Spencer's + ANSI string package, when GNU libc comes out I'll replace this...). */ + +#ifndef strcspn +inline int +Key_List::strcspn (const char *s, const char *reject) +{ + T (Trace t ("Key_List::strcspn");) + const char *scan; + const char *rej_scan; + int count = 0; + + for (scan = s; *scan; scan++) + { + + for (rej_scan = reject; *rej_scan; rej_scan++) + if (*scan == *rej_scan) + return count; + + count++; + } + + return count; +} +#endif + +/* Sets up the Return_Type, the Struct_Tag type and the Array_Type + based upon various user Options. */ + +void +Key_List::set_output_types (void) +{ + T (Trace t ("Key_List::set_output_types");) + if (option[TYPE]) + { + array_type = get_array_type (); + if (!array_type) + /* Something's wrong, but we'll catch it later on, in read_keys()... */ + return; + /* Yow, we've got a user-defined type... */ + int i = strcspn (array_type, "{\n\0"); + /* Remove trailing whitespace. */ + while (i > 0 && strchr (" \t", array_type[i-1])) + i--; + int struct_tag_length = i; + + /* Set `struct_tag' to a naked "struct something". */ + char *structtag = new char[struct_tag_length + 1]; + strncpy (structtag, array_type, struct_tag_length); + structtag[struct_tag_length] = '\0'; + struct_tag = structtag; + + /* 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 *rettype = new char[struct_tag_length + 3]; + strncpy (rettype, array_type, struct_tag_length); + rettype[struct_tag_length] = ' '; + rettype[struct_tag_length + 1] = '*'; + rettype[struct_tag_length + 2] = '\0'; + return_type = rettype; + } +} + +/* Reads in all keys from standard input and creates a linked list pointed + to by Head. This list is then quickly checked for ``links,'' i.e., + unhashable elements possessing identical key sets and lengths. */ + +void +Key_List::read_keys (void) +{ + T (Trace t ("Key_List::read_keys");) + char *ptr; + + include_src = save_include_src (); + set_output_types (); + + /* Oops, problem with the input file. */ + if (! (ptr = Read_Line::get_line ())) + { + fprintf (stderr, "No words in input file, did you forget to prepend %s or use -t accidentally?\n", "%%"); + exit (1); + } + + /* Read in all the keywords from the input file. */ + else + { + const char *delimiter = option.get_delimiter (); + List_Node *temp, *trail = 0; + + head = new List_Node (ptr, strcspn (ptr, delimiter)); + + for (temp = head; + (ptr = Read_Line::get_line ()) && strcmp (ptr, "%%"); + temp = temp->next) + { + temp->next = new List_Node (ptr, strcspn (ptr, delimiter)); + total_keys++; + } + + /* See if any additional C code is included at end of this file. */ + if (ptr) + additional_code = 1; + + /* Hash table this number of times larger than keyword number. */ + int table_size = (list_len = total_keys) * TABLE_MULTIPLE; + +#if LARGE_STACK_ARRAYS + /* By allocating the memory here we save on dynamic allocation overhead. + Table must be a power of 2 for the hash function scheme to work. */ + List_Node *table[POW (table_size)]; +#else + // Note: we don't use new, because that invokes a custom operator new. + int malloc_size = POW (table_size) * sizeof(List_Node*); + if (malloc_size == 0) malloc_size = 1; + List_Node **table = (List_Node**)malloc(malloc_size); + if (table == NULL) + abort (); +#endif + + /* Make large hash table for efficiency. */ + Hash_Table found_link (table, table_size); + + /* Test whether there are any links and also set the maximum length of + an identifier in the keyword list. */ + + for (temp = head; temp; temp = temp->next) + { + List_Node *ptr = found_link (temp, option[NOLENGTH]); + + /* Check for links. We deal with these by building an equivalence class + of all duplicate values (i.e., links) so that only 1 keyword is + representative of the entire collection. This *greatly* simplifies + processing during later stages of the program. */ + + if (ptr) + { + total_duplicates++; + list_len--; + trail->next = temp->next; + temp->link = ptr->link; + ptr->link = temp; + + /* Complain if user hasn't enabled the duplicate option. */ + if (!option[DUP] || option[DEBUG]) + fprintf (stderr, "Key link: \"%s\" = \"%s\", with key set \"%s\".\n", + temp->key, ptr->key, temp->char_set); + } + else + trail = temp; + + /* Update minimum and maximum keyword length, if needed. */ + if (max_key_len < temp->length) + max_key_len = temp->length; + if (min_key_len > temp->length) + min_key_len = temp->length; + } + +#if !LARGE_STACK_ARRAYS + free ((char *) table); +#endif + + /* Exit program if links exists and option[DUP] not set, since we can't continue */ + 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,\ntry different key positions or use option -D.\n", + total_duplicates); + exit (1); + } + } + if (option[ALLCHARS]) + option.set_keysig_size (max_key_len); + } +} + +/* Recursively merges two sorted lists together to form one sorted list. The + ordering criteria is by frequency of occurrence of elements in the key set + or by the hash value. This is a kludge, but permits nice sharing of + almost identical code without incurring the overhead of a function + call comparison. */ + +List_Node * +Key_List::merge (List_Node *list1, List_Node *list2) +{ + T (Trace t ("Key_List::merge");) + List_Node *result; + List_Node **resultp = &result; + for (;;) + { + if (!list1) + { + *resultp = list2; + break; + } + if (!list2) + { + *resultp = list1; + break; + } + if (occurrence_sort && list1->occurrence < list2->occurrence + || hash_sort && list1->hash_value > list2->hash_value) + { + *resultp = list2; + resultp = &list2->next; list2 = list1; list1 = *resultp; + } + else + { + *resultp = list1; + resultp = &list1->next; list1 = *resultp; + } + } + return result; +} + +/* Applies the merge sort algorithm to recursively sort the key list by + frequency of occurrence of elements in the key set. */ + +List_Node * +Key_List::merge_sort (List_Node *head) +{ + T (Trace t ("Key_List::merge_sort");) + if (!head || !head->next) + return head; + else + { + List_Node *middle = head; + List_Node *temp = head->next->next; + + while (temp) + { + temp = temp->next; + middle = middle->next; + if (temp) + temp = temp->next; + } + + temp = middle->next; + middle->next = 0; + return merge (merge_sort (head), merge_sort (temp)); + } +} + +/* Returns the frequency of occurrence of elements in the key set. */ + +inline int +Key_List::get_occurrence (List_Node *ptr) +{ + T (Trace t ("Key_List::get_occurrence");) + int value = 0; + + for (const char *temp = ptr->char_set; *temp; temp++) + value += occurrences[(unsigned char)(*temp)]; + + return value; +} + +/* Enables the index location of all key set elements that are now + determined. */ + +inline void +Key_List::set_determined (List_Node *ptr) +{ + T (Trace t ("Key_List::set_determined");) + for (const char *temp = ptr->char_set; *temp; temp++) + determined[(unsigned char)(*temp)] = 1; +} + +/* Returns TRUE if PTR's key set is already completely determined. */ + +inline int +Key_List::already_determined (List_Node *ptr) +{ + T (Trace t ("Key_List::already_determined");) + int is_determined = 1; + + for (const char *temp = ptr->char_set; is_determined && *temp; temp++) + is_determined = determined[(unsigned char)(*temp)]; + + return is_determined; +} + +/* Reorders the table by first sorting the list so that frequently occuring + keys appear first, and then the list is reorded so that keys whose values + are already determined will be placed towards the front of the list. This + helps prune the search time by handling inevitable collisions early in the + search process. See Cichelli's paper from Jan 1980 JACM for details.... */ + +void +Key_List::reorder (void) +{ + T (Trace t ("Key_List::reorder");) + List_Node *ptr; + for (ptr = head; ptr; ptr = ptr->next) + ptr->occurrence = get_occurrence (ptr); + + hash_sort = 0; + occurrence_sort = 1; + + for (ptr = head = merge_sort (head); ptr->next; ptr = ptr->next) + { + set_determined (ptr); + + if (already_determined (ptr->next)) + continue; + else + { + List_Node *trail_ptr = ptr->next; + List_Node *run_ptr = trail_ptr->next; + + for (; run_ptr; run_ptr = trail_ptr->next) + { + + if (already_determined (run_ptr)) + { + trail_ptr->next = run_ptr->next; + run_ptr->next = ptr->next; + ptr = ptr->next = run_ptr; + } + else + trail_ptr = run_ptr; + } + } + } +} + +/* ============================ Output routines ============================ */ + +/* 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"; +} + +/* A cast from `char' to a valid array index. */ +static const char *char_to_index; + +/* ------------------------------------------------------------------------- */ + +/* Computes the maximum and minimum hash values. Since the + list is already sorted by hash value all we need to do is + find the final item! */ + +void +Key_List::compute_min_max (void) +{ + T (Trace t ("Key_List::compute_min_max");) + List_Node *temp; + for (temp = head; temp->next; temp = temp->next) + ; + + min_hash_value = head->hash_value; + max_hash_value = temp->hash_value; +} + +/* ------------------------------------------------------------------------- */ + +/* Returns the number of different hash values. */ + +int +Key_List::num_hash_values (void) +{ + T (Trace t ("Key_List::num_hash_values");) + int count = 1; + List_Node *temp; + int value; + + for (temp = head, value = temp->hash_value; temp->next; ) + { + temp = temp->next; + if (value != temp->hash_value) + { + value = temp->hash_value; + 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 () +{ + T (Trace t ("Output_Defines::output_start");) + printf ("\n"); +} + +void Output_Defines::output_item (const char *name, int value) +{ + T (Trace t ("Output_Defines::output_item");) + printf ("#define %s %d\n", name, value); +} + +void Output_Defines::output_end () +{ + T (Trace t ("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; + int pending_comma; +}; + +void Output_Enum::output_start () +{ + T (Trace t ("Output_Enum::output_start");) + printf ("%senum\n" + "%s {\n", + indentation, indentation); + pending_comma = 0; +} + +void Output_Enum::output_item (const char *name, int value) +{ + T (Trace t ("Output_Enum::output_item");) + if (pending_comma) + printf (",\n"); + printf ("%s %s = %d", indentation, name, value); + pending_comma = 1; +} + +void Output_Enum::output_end () +{ + T (Trace t ("Output_Enum::output_end");) + if (pending_comma) + printf ("\n"); + printf ("%s };\n\n", indentation); +} + +/* Outputs the maximum and minimum hash values etc. */ + +void +Key_List::output_constants (struct Output_Constants& style) +{ + T (Trace t ("Key_List::output_constants");) + + 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 (); +} + +/* ------------------------------------------------------------------------- */ + +/* Outputs a keyword, as a string: enclosed in double quotes, escaping + backslashes and double quote characters. */ + +static void +output_string (const char *key) +{ + T (Trace t ("output_string");) + char c; + + putchar ('"'); + while (c = *key++, c != '\0') + { + if (c == '"' || c == '\\') + putchar ('\\'); + putchar (c); + } + putchar ('"'); +} + +/* ------------------------------------------------------------------------- */ + +/* Outputs a type and a const specifier. + 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] == '*') + printf ("%s %s", type_string, const_string); + else + 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 +{ + T (Trace t ("Output_Expr1::output_expr");) + 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 +{ + T (Trace t ("Output_Expr2::output_expr");) + printf ("%s%s", p1, p2); +} + +#endif + +/* --------------------- Output_Compare and subclasses --------------------- */ + +/* This class outputs a comparison expression. */ + +struct Output_Compare +{ + virtual void output_comparison (const Output_Expr& expr1, + const Output_Expr& expr2) const = 0; + Output_Compare () {} + virtual ~Output_Compare () {} +}; + +/* 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 +{ + T (Trace t ("Output_Compare_Strcmp::output_comparison");) + printf ("*"); + expr1.output_expr (); + printf (" == *"); + expr2.output_expr (); + printf (" && !strcmp ("); + expr1.output_expr (); + printf (" + 1, "); + expr2.output_expr (); + printf (" + 1)"); +} + +/* 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 +{ + T (Trace t ("Output_Compare_Strncmp::output_comparison");) + printf ("*"); + expr1.output_expr (); + printf (" == *"); + expr2.output_expr (); + printf (" && !strncmp ("); + expr1.output_expr (); + printf (" + 1, "); + expr2.output_expr (); + printf (" + 1, len - 1)"); +} + +/* ------------------------------------------------------------------------- */ + +/* Generates C code for the hash function that returns the + proper encoding for each key word. */ + +void +Key_List::output_hash_function (void) +{ + T (Trace t ("Key_List::output_hash_function");) + const int max_column = 10; + int field_width; + + /* Calculate maximum number of digits required for MAX_HASH_VALUE. */ + field_width = 2; + for (int trunc = max_hash_value; (trunc /= 10) > 0;) + field_width++; + + /* Output the function's head. */ + if (option[CPLUSPLUS]) + printf ("inline "); + else if (option[KRC] | option[C] | option[ANSIC]) + printf ("#ifdef __GNUC__\n" + "__inline\n" + "#endif\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. */ + printf (" static %s%s asso_values[] =\n" + " {", + const_readonly_array, + smallest_integral_type (max_hash_value + 1)); + + for (int count = 0; count < ALPHA_SIZE; count++) + { + if (count > 0) + printf (","); + if (!(count % max_column)) + printf ("\n "); + printf ("%*d", field_width, + occurrences[count] ? asso_values[count] : max_hash_value + 1); + } + + printf ("\n" + " };\n"); + + /* Optimize special case of ``-k 1,$'' */ + if (option[DEFAULTCHARS]) + printf (" return %sasso_values[%sstr[len - 1]] + asso_values[%sstr[0]];\n", + option[NOLENGTH] ? "" : "len + ", + char_to_index, char_to_index); + else + { + int key_pos; + + option.reset (); + + /* Get first (also highest) key position. */ + key_pos = option.get (); + + if (!option[ALLCHARS] && (key_pos == WORD_END || 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 + "); + + for (; key_pos != WORD_END; ) + { + printf ("asso_values[%sstr[%d]]", char_to_index, key_pos - 1); + if ((key_pos = option.get ()) != EOS) + printf (" + "); + else + break; + } + + if (key_pos == WORD_END) + printf ("asso_values[%sstr[len - 1]]", char_to_index); + + 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"); + + /* User wants *all* characters considered in hash. */ + if (option[ALLCHARS]) + { + for (int i = max_key_len; i > 0; i--) + printf (" case %d:\n" + " hval += asso_values[%sstr[%d]];\n", + i, char_to_index, i - 1); + + printf (" break;\n" + " }\n" + " return hval;\n"); + } + else /* do the hard part... */ + { + while (key_pos != WORD_END && key_pos > max_key_len) + if ((key_pos = option.get ()) == EOS) + break; + + if (key_pos != EOS && key_pos != WORD_END) + { + int i = key_pos; + do + { + for ( ; i >= key_pos; i--) + printf (" case %d:\n", i); + + printf (" hval += asso_values[%sstr[%d]];\n", + char_to_index, key_pos - 1); + + key_pos = option.get (); + } + while (key_pos != EOS && key_pos != WORD_END); + + for ( ; i >= min_key_len; i--) + printf (" case %d:\n", i); + } + + printf (" break;\n" + " }\n" + " return hval"); + if (key_pos == WORD_END) + printf (" + asso_values[%sstr[len - 1]]", char_to_index); + printf (";\n"); + } + } + } + printf ("}\n\n"); +} + +/* ------------------------------------------------------------------------- */ + +/* Prints out a table of keyword lengths, for use with the + comparison code in generated function ``in_word_set''. */ + +void +Key_List::output_keylength_table (void) +{ + T (Trace t ("Key_List::output_keylength_table");) + const int columns = 14; + int index; + int column; + const char *indent = option[GLOBAL] ? "" : " "; + List_Node *temp; + + 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. */ + + column = 0; + for (temp = head, index = 0; temp; temp = temp->next) + { + if (option[SWITCH] && !option[TYPE] + && !(temp->link + || (temp->next && temp->hash_value == temp->next->hash_value))) + continue; + + if (index < temp->hash_value && !option[SWITCH] && !option[DUP]) + { + /* Some blank entries. */ + for ( ; index < temp->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", temp->length); + + /* Deal with links specially. */ + if (temp->link) // implies option[DUP] + for (List_Node *links = temp->link; links; links = links->link) + { + ++index; + printf (","); + if ((column++ % columns) == 0) + printf("\n%s ", indent); + printf ("%3d", links->length); + } + + index++; + } + + printf ("\n%s };\n", indent); + if (option[GLOBAL]) + printf ("\n"); +} + +/* ------------------------------------------------------------------------- */ + +static void +output_keyword_entry (List_Node *temp, const char *indent) +{ + printf ("%s ", indent); + if (option[TYPE]) + printf ("{"); + output_string (temp->key); + if (option[TYPE]) + printf (",%s}", temp->rest); + if (option[DEBUG]) + printf (" /* hash value = %d, index = %d */", + temp->hash_value, temp->index); +} + +static void +output_keyword_blank_entries (int count, const char *indent) +{ + const int columns = 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 ("{\"\"}"); + else + printf ("\"\""); + column++; + } +} + +/* Prints out the array containing the key words for the hash function. */ + +void +Key_List::output_keyword_table (void) +{ + T (Trace t ("Key_List::output_keyword_table");) + const char *indent = option[GLOBAL] ? "" : " "; + int index; + List_Node *temp; + + printf ("%sstatic ", + indent); + output_const_type (const_readonly_array, struct_tag); + 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->next) + { + if (option[SWITCH] && !option[TYPE] + && !(temp->link + || (temp->next && temp->hash_value == temp->next->hash_value))) + continue; + + if (index > 0) + printf (",\n"); + + if (index < temp->hash_value && !option[SWITCH] && !option[DUP]) + { + /* Some blank entries. */ + output_keyword_blank_entries (temp->hash_value - index, indent); + printf (",\n"); + index = temp->hash_value; + } + + temp->index = index; + + output_keyword_entry (temp, indent); + + /* Deal with links specially. */ + if (temp->link) // implies option[DUP] + for (List_Node *links = temp->link; links; links = links->link) + { + links->index = ++index; + printf (",\n"); + output_keyword_entry (links, 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 +Key_List::output_lookup_array (void) +{ + T (Trace t ("Key_List::output_lookup_array");) + 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. */ + }; + +#if LARGE_STACK_ARRAYS + duplicate_entry duplicates[total_duplicates]; + int lookup_array[max_hash_value + 1 + 2*total_duplicates]; +#else + // Note: we don't use new, because that invokes a custom operator new. + duplicate_entry *duplicates = (duplicate_entry *) + malloc (total_duplicates * sizeof(duplicate_entry) + 1); + int *lookup_array = (int *) + malloc ((max_hash_value + 1 + 2*total_duplicates) * sizeof(int)); + if (duplicates == NULL || lookup_array == NULL) + abort(); +#endif + 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 (List_Node *temp = head; temp; temp = temp->next) + { + int hash_value = temp->hash_value; + lookup_array[hash_value] = temp->index; + if (option[DEBUG]) + fprintf (stderr, "keyword = %s, index = %d\n", + temp->key, temp->index); + if (temp->link + || (temp->next && hash_value == temp->next->hash_value)) + { + /* Start a duplicate entry. */ + dup_ptr->hash_value = hash_value; + dup_ptr->index = temp->index; + dup_ptr->count = 1; + + for (;;) + { + for (List_Node *ptr = temp->link; ptr; ptr = ptr->link) + { + dup_ptr->count++; + if (option[DEBUG]) + fprintf (stderr, + "static linked keyword = %s, index = %d\n", + ptr->key, ptr->index); + } + + if (!(temp->next && hash_value == temp->next->hash_value)) + break; + + temp = temp->next; + + dup_ptr->count++; + if (option[DEBUG]) + fprintf (stderr, "dynamic linked keyword = %s, index = %d\n", + temp->key, temp->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->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); + +#if !LARGE_STACK_ARRAYS + free ((char *) duplicates); + free ((char *) lookup_array); +#endif + } +} + +/* ------------------------------------------------------------------------- */ + +/* Generate all the tables needed for the lookup function. */ + +void +Key_List::output_lookup_tables (void) +{ + T (Trace t ("Key_List::output_lookup_tables");) + + 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 List_Node * +output_switch_case (List_Node *list, int indent, int *jumps_away) +{ + T (Trace t ("output_switch_case");) + + if (option[DEBUG]) + printf ("%*s/* hash value = %4d, keyword = \"%s\" */\n", + indent, "", list->hash_value, list->key); + + if (option[DUP] + && (list->link + || (list->next && list->hash_value == list->next->hash_value))) + { + if (option[LENTABLE]) + printf ("%*slengthptr = &lengthtable[%d]\n", + indent, "", list->index); + printf ("%*swordptr = &%s[%d];\n", + indent, "", option.get_wordlist_name (), list->index); + + int count = 0; + for (List_Node *temp = list; ; temp = temp->next) + { + for (List_Node *links = temp; links; links = links->link) + count++; + if (!(temp->next && temp->hash_value == temp->next->hash_value)) + break; + } + + 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->length, + indent, ""); + indent += 4; + } + printf ("%*sresword = ", + indent, ""); + if (option[TYPE]) + printf ("&%s[%d]", option.get_wordlist_name (), list->index); + else + output_string (list->key); + printf (";\n"); + printf ("%*sgoto compare;\n", + indent, ""); + if (option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", + indent, ""); + } + else + *jumps_away = 1; + } + + while (list->next && list->hash_value == list->next->hash_value) + list = list->next; + list = list->next; + return list; +} + +/* Output a total of size cases, grouped into num_switches switch statements, + where 0 < num_switches <= size. */ + +static void +output_switches (List_Node *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent) +{ + T (Trace t ("output_switches");) + + 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 = (int)((double)size / (double)num_switches * (double)part1 + 0.5); + int size2 = size - size1; + + List_Node *temp = list; + for (int count = size1; count > 0; count--) + { + while (temp->hash_value == temp->next->hash_value) + temp = temp->next; + temp = temp->next; + } + + printf ("%*sif (key < %d)\n" + "%*s {\n", + indent, "", temp->hash_value, + indent, ""); + + output_switches (list, part1, size1, min_hash_value, temp->hash_value-1, indent+4); + + printf ("%*s }\n" + "%*selse\n" + "%*s {\n", + indent, "", indent, "", indent, ""); + + output_switches (temp, part2, size2, temp->hash_value, max_hash_value, indent+4); + + printf ("%*s }\n", + indent, ""); + } + else + { + /* Output a single switch. */ + int lowest_case_value = list->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->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 +Key_List::output_lookup_function_body (const Output_Compare& comparison) +{ + T (Trace t ("Key_List::output_lookup_function_body");) + + 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]) + { + 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, struct_tag); + printf ("*wordptr;\n"); + printf (" register "); + output_const_type (const_readonly_array, struct_tag); + 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); + + if (option[DUP]) + { + int indent = 8; + printf ("%*s return 0;\n" + "%*smulticompare:\n" + "%*s while (wordptr < wordendptr)\n" + "%*s {\n", + indent, "", 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_key_name ()); + else + printf ("*wordptr"); + 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", + indent, "", indent, ""); + } + printf (" return 0;\n" + " compare:\n"); + if (option[TYPE]) + { + printf (" {\n" + " register %schar *s = resword->%s;\n\n" + " if (", + const_always, option.get_key_name ()); + 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_key_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, ""); + } + 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, struct_tag); + printf ("*wordptr = &%s[TOTAL_KEYWORDS + lookup[offset]];\n", + option.get_wordlist_name ()); + printf ("%*s register ", + indent, ""); + output_const_type (const_readonly_array, struct_tag); + 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_key_name ()); + else + printf ("*wordptr"); + 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" + "%*s}\n", + indent, "", indent, "", indent, "", indent, ""); + } + else + { + int indent = 8; + if (option[LENTABLE]) + { + printf ("%*sif (len == lengthtable[key])\n", + indent, ""); + indent += 2; + } + + printf ("%*s{\n" + "%*s register %schar *s = %s[key]", + indent, "", + indent, "", const_always, option.get_wordlist_name ()); + + if (option[TYPE]) + printf (".%s", option.get_key_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[key]", option.get_wordlist_name ()); + else + printf ("s"); + printf (";\n" + "%*s}\n", + indent, ""); + } + } + printf (" }\n" + " return 0;\n"); +} + +/* Generates C code for the lookup function. */ + +void +Key_List::output_lookup_function (void) +{ + T (Trace t ("Key_List::output_lookup_function");) + + /* 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[GLOBAL]) + output_lookup_tables (); + + 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 +Key_List::output (void) +{ + T (Trace t ("Key_List::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 *"); + } + + char_to_index = (option[SEVENBIT] ? "" : "(unsigned char)"); + + 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); + Options::print_options (); + + printf ("%s\n", include_src); + + if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */ + printf ("%s;\n", array_type); + + 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[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[GLOBAL]) + output_lookup_tables (); + + output_lookup_function (); + + if (additional_code) + for (int c; (c = getchar ()) != EOF; putchar (c)) + ; + + fflush (stdout); +} + +/* ========================= End of Output routines ========================= */ + +/* Sorts the keys by hash value. */ + +void +Key_List::sort (void) +{ + T (Trace t ("Key_List::sort");) + hash_sort = 1; + occurrence_sort = 0; + + head = merge_sort (head); +} + +/* Dumps the key list to stderr stream. */ + +void +Key_List::dump () +{ + T (Trace t ("Key_List::dump");) + int field_width = option.get_max_keysig_size (); + + fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n", + field_width, "char_set"); + + for (List_Node *ptr = head; ptr; ptr = ptr->next) + fprintf (stderr, "%11d,%11d,%6d, %*s, %s\n", + ptr->hash_value, ptr->length, ptr->index, + field_width, ptr->char_set, ptr->key); +} + +/* Simple-minded constructor action here... */ + +Key_List::Key_List (void) +{ + T (Trace t ("Key_List::Key_List");) + total_keys = 1; + max_key_len = INT_MIN; + min_key_len = INT_MAX; + array_type = 0; + return_type = 0; + struct_tag = 0; + head = 0; + total_duplicates = 0; + additional_code = 0; +} + +/* Returns the length of entire key list. */ + +int +Key_List::keyword_list_length (void) +{ + T (Trace t ("Key_List::keyword_list_length");) + return list_len; +} + +/* Returns length of longest key read. */ + +int +Key_List::max_key_length (void) +{ + T (Trace t ("Key_List::max_key_length");) + return max_key_len; +} + diff --git a/src/key-list.h b/src/key-list.h new file mode 100644 index 0000000..98b8fa5 --- /dev/null +++ b/src/key-list.h @@ -0,0 +1,96 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Data and function member declarations for the keyword list class. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +/* The key word list is a useful abstraction that keeps track of + various pieces of information that enable that fast generation + of the Gen_Perf.hash function. A Key_List is a singly-linked + list of List_Nodes. */ + +#ifndef key_list_h +#define key_list_h 1 + +#include "list-node.h" +#include "vectors.h" +#include "read-line.h" + +/* OSF/1 cxx needs these forward declarations. */ +struct Output_Constants; +struct Output_Compare; + +class Key_List : private Read_Line, public Vectors +{ +private: + const char *array_type; /* Pointer to the type for word list. */ + const char *return_type; /* Pointer to return type for lookup function. */ + const char *struct_tag; /* Shorthand for user-defined struct tag type. */ + const char *include_src; /* C source code to be included verbatim. */ + int max_key_len; /* Maximum length of the longest keyword. */ + int min_key_len; /* Minimum length of the shortest keyword. */ + int min_hash_value; /* Minimum hash value for all keywords. */ + int max_hash_value; /* Maximum hash value for all keywords. */ + int occurrence_sort; /* True if sorting by occurrence. */ + int hash_sort; /* True if sorting by hash value. */ + int additional_code; /* True if any additional C code is included. */ + int list_len; /* Length of head's Key_List, not counting duplicates. */ + int total_keys; /* Total number of keys, counting duplicates. */ + static int determined[MAX_ALPHA_SIZE]; /* Used in function reorder, below. */ + static int get_occurrence (List_Node *ptr); +#ifndef strcspn + static int strcspn (const char *s, const char *reject); +#endif + static int already_determined (List_Node *ptr); + static void set_determined (List_Node *ptr); + void compute_min_max (void); + int num_hash_values (void); + void output_constants (struct Output_Constants&); + void output_hash_function (void); + void output_keylength_table (void); + void output_keyword_table (void); + void output_lookup_array (void); + void output_lookup_tables (void); + void output_lookup_function_body (const struct Output_Compare&); + void output_lookup_function (void); + void set_output_types (void); + void dump (void); + const char *get_array_type (void); + const char *save_include_src (void); + const char *get_special_input (char delimiter); + List_Node *merge (List_Node *list1, List_Node *list2); + List_Node *merge_sort (List_Node *head); + +protected: + List_Node *head; /* Points to the head of the linked list. */ + int total_duplicates; /* Total number of duplicate hash values. */ + +public: + Key_List (void); + ~Key_List (void); + int keyword_list_length (void); + int max_key_length (void); + void reorder (void); + void sort (void); + void read_keys (void); + void output (void); +}; + +#endif diff --git a/src/list-node.cc b/src/list-node.cc new file mode 100644 index 0000000..6c78889 --- /dev/null +++ b/src/list-node.cc @@ -0,0 +1,101 @@ +/* Creates and initializes a new list node. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "list-node.h" + +#include +#include /* declares exit() */ +#include "options.h" +#include "trace.h" + +/* Sorts the key set alphabetically to speed up subsequent operations. + Uses insertion sort since the set is probably quite small. */ + +inline void +List_Node::set_sort (char *base, int len) +{ + T (Trace t ("List_Node::set_sort");) + int i, j; + + for (i = 0, j = len - 1; i < j; i++) + { + char curr, tmp; + + for (curr = i + 1, tmp = base[curr]; curr > 0 && tmp < base[curr-1]; curr--) + base[curr] = base[curr - 1]; + + base[curr] = tmp; + + } +} + +/* Initializes a List_Node. This requires obtaining memory for the CHAR_SET + initializing them using the information stored in the KEY_POSITIONS array in Options, + and checking for simple errors. It's important to note that KEY and REST are + both pointers to the different offsets into the same block of dynamic memory pointed + to by parameter K. The data member REST is used to store any additional fields + of the input file (it is set to the "" string if Option[TYPE] is not enabled). + This is useful if the user wishes to incorporate a lookup structure, + rather than just an array of keys. Finally, KEY_NUMBER contains a count + of the total number of keys seen so far. This is used to initialize + the INDEX field to some useful value. */ + +List_Node::List_Node (char *k, int len): link (0), next (0), + key (k), rest (option[TYPE] ? k + len + 1 : ""), length (len), index (0) +{ + T (Trace t ("List_Node::List_Node");) + char *ptr = new char[(option[ALLCHARS] ? len : option.get_max_keysig_size ()) + 1]; + char *key_set = ptr; + k[len] = '\0'; /* Null terminate KEY to separate it from REST. */ + + if (option[ALLCHARS]) /* Use all the character position in the KEY. */ + for (; *k; k++, ptr++) + ++occurrences[(unsigned char)(*ptr = *k)]; + else /* Only use those character positions specified by the user. */ + { + int i; + + /* Iterate thru the list of key_positions, initializing occurrences table + and char_set (via char * pointer ptr). */ + + for (option.reset (); (i = option.get ()) != EOS; ) + { + if (i == WORD_END) /* Special notation for last KEY position, i.e. '$'. */ + *ptr = key[len - 1]; + else if (i <= len) /* Within range of KEY length, so we'll keep it. */ + *ptr = key[i - 1]; + else /* Out of range of KEY length, so we'll just skip it. */ + continue; + ++occurrences[(unsigned char)(*ptr++)]; + } + + /* Didn't get any hits and user doesn't want to consider the + keylength, so there are essentially no usable hash positions! */ + if (ptr == char_set && option[NOLENGTH]) + { + fprintf (stderr, "Can't hash keyword %s with chosen key positions.\n", key); + exit (1); + } + } + *ptr = '\0'; /* Terminate this bastard.... */ + /* Sort the KEY_SET items alphabetically. */ + set_sort (key_set, ptr - key_set); + char_set = key_set; +} diff --git a/src/list-node.h b/src/list-node.h new file mode 100644 index 0000000..630d91a --- /dev/null +++ b/src/list-node.h @@ -0,0 +1,45 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Data and function members for defining values and operations of a list node. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef list_node_h +#define list_node_h 1 + +#include "vectors.h" + +struct List_Node : private Vectors +{ + List_Node *link; /* TRUE if key has an identical KEY_SET as another key. */ + List_Node *next; /* Points to next element on the list. */ + const char *key; /* Each keyword string stored here. */ + const char *rest; /* Additional information for building hash function. */ + const char *char_set; /* Set of characters to hash, specified by user. */ + int length; /* Length of the key. */ + int hash_value; /* Hash value for the key. */ + int occurrence; /* A metric for frequency of key set occurrences. */ + int index; /* Position of this node relative to other nodes. */ + + List_Node (char *key, int len); + static void set_sort (char *base, int len); +}; + +#endif diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..4e08633 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,72 @@ +/* Driver program for the Gen_Perf hash function generator + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +/* Simple driver program for the Gen_Perf.hash function generator. + Most of the hard work is done in class Gen_Perf and its class methods. */ + +#include "config.h" +#include +#if LARGE_STACK_ARRAYS && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#endif + +#include +#include "options.h" +#include "gen-perf.h" +#include "trace.h" + +int +main (int argc, char *argv[]) +{ + T (Trace t ("main");) + +#if LARGE_STACK_ARRAYS && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK) + /* Get rid of any avoidable limit on stack size. */ + { + struct rlimit rlim; + if (getrlimit (RLIMIT_STACK, &rlim) == 0) + if (rlim.rlim_cur < rlim.rlim_max) + { + rlim.rlim_cur = rlim.rlim_max; + setrlimit (RLIMIT_STACK, &rlim); + } + } +#endif /* RLIMIT_STACK */ + + /* Sets the Options. */ + option (argc, argv); + + /* Initializes the key word list. */ + Gen_Perf generate_table; + + /* Generates and prints the Gen_Perf hash table. */ + int status = generate_table (); + + /* Don't use exit() here, it skips the destructors. */ + return status; +} diff --git a/src/new.cc b/src/new.cc new file mode 100644 index 0000000..8c6728e --- /dev/null +++ b/src/new.cc @@ -0,0 +1,87 @@ +/* Defines a buffered memory allocation abstraction that reduces calls to + malloc. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "config.h" +#include +#include /* declares malloc(), exit() */ +#include "trace.h" + +/* Determine default alignment. If your C++ compiler does not + like this then try something like #define DEFAULT_ALIGNMENT 8. */ +struct fooalign {char x; double d;}; +const int ALIGNMENT = ((char *)&((struct fooalign *) 0)->d - (char *)0); + +/* Provide an abstraction that cuts down on the number of + calls to NEW by buffering the memory pool from which + strings are allocated. */ + +void * +operator new (size_t size) +{ + T (Trace t ("operator new");) + static char *buf_start = 0; /* Large array used to reduce calls to NEW. */ + static char *buf_end = 0; /* Indicates end of BUF_START. */ + static size_t buf_size = 4096; /* Size of buffer pointed to by BUF_START. */ + char *temp; + + /* Align this on correct boundaries, just to be safe... */ + size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; + + /* If we are about to overflow our buffer we'll just grab another + chunk of memory. Since we never free the original memory it + doesn't matter that no one points to the beginning of that + chunk. Note we use a heuristic that grows the buffer either by + size of the request or by twice the previous size, whichever is + larger. */ + + if (buf_start + size >= buf_end) + { + buf_size *= 2; + if (buf_size < size) + buf_size = size; + if ((buf_start = (char *)malloc (buf_size)) != (char *)0) + buf_end = buf_start + buf_size; + else + { + fprintf (stderr, "Virtual memory exhausted in `operator new'\n"); + exit (1); + } + } + + temp = buf_start; + buf_start += size; + return temp; +} + +/* We need this deletion operator in order to make the linker happy. + Because `operator new' and `operator delete' always come together. */ + +void +operator delete (void *ptr) +#ifdef HAVE_THROW_DECL + throw() +#endif +{ + T (Trace t ("operator delete");) + // We cannot call free here, as it doesn't match the mallocs. + // free ((char *) ptr); + (void) ptr; +} diff --git a/src/options.cc b/src/options.cc new file mode 100644 index 0000000..7be9746 --- /dev/null +++ b/src/options.cc @@ -0,0 +1,668 @@ +/* Handles parsing the Options provided to the user. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include +#include /* declares atoi(), abs(), exit() */ +#include /* declares strcmp() */ +#include "getopt.h" +#include "options.h" +#include "iterator.h" +#include "trace.h" +#include "vectors.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_NAME = "in_word_set"; + +/* Default name for the key component. */ +static const char *const DEFAULT_KEY = "name"; + +/* 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 delimiters that separate keywords from their attributes. */ +static const char *const DEFAULT_DELIMITERS = ",\n"; + +int Options::option_word; +int Options::total_switches; +int Options::total_keysig_size; +int Options::size; +int Options::key_pos; +int Options::jump; +int Options::initial_asso_value; +int Options::argument_count; +int Options::iterations; +char **Options::argument_vector; +const char *Options::function_name; +const char *Options::key_name; +const char *Options::class_name; +const char *Options::hash_name; +const char *Options::wordlist_name; +const char *Options::delimiters; +char Options::key_positions[MAX_KEY_POS]; + +/* Prints program usage to given stream. */ + +void +Options::short_usage (FILE * strm) +{ + T (Trace t ("Options::short_usage");) + fprintf (strm, "Usage: %s [-cCdDef[num]GhHiIjkKlLnNorsStTvWZ7] [input-file]\n" + "Try `%s --help' for more information.\n", + program_name, program_name); +} + +void +Options::long_usage (FILE * strm) +{ + T (Trace t ("Options::long_usage");) + fprintf (strm, + "GNU `gperf' generates perfect hash functions.\n" + "\n" + "Usage: %s [OPTION]... [INPUT-FILE]\n" + "\n" + "If a long option shows an argument as mandatory, then it is mandatory\n" + "for the equivalent short option also.\n" + "\n" + "Input file interpretation:\n" + " -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\".\n" + " -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" + "\n" + "Language for the output code:\n" + " -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" + "\n" + "Details in the output code:\n" + " -K, --slot-name=NAME Select name of the keyword component in the keyword\n" + " structure.\n" + " -H, --hash-fn-name=NAME\n" + " Specify name of generated hash function. Default is\n" + " `hash'.\n" + " -N, --lookup-fn-name=NAME\n" + " Specify name of generated lookup function. Default\n" + " name is `in_word_set'.\n" + " -Z, --class-name=NAME Specify name of generated C++ class. Default name is\n" + " `Perfect_Hash'.\n" + " -7, --seven-bit Assume 7-bit characters.\n" + " -c, --compare-strncmp Generate comparison code using strncmp rather than\n" + " strcmp.\n" + " -C, --readonly-tables Make the contents of generated lookup tables\n" + " constant, i.e., readonly.\n" + " -E, --enum Define constant values using an enum local to the\n" + " lookup function rather than with defines.\n" + " -I, --includes Include the necessary system include file \n" + " at the beginning of the code.\n" + " -G, --global 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" + " -W, --word-array-name=NAME\n" + " Specify name of word list array. Default name is\n" + " `wordlist'.\n" + " -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" + " -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" + "\n" + "Algorithm employed by gperf:\n" + " -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" + " -l, --compare-strlen Compare key lengths before trying a string\n" + " comparison. This helps cut down on the number of\n" + " string comparisons made during the lookup.\n" + " -D, --duplicates Handle keywords that hash to duplicate values. This\n" + " is useful for certain highly redundant keyword sets.\n" + " -f, --fast=ITERATIONS Generate the gen-perf.hash function ``fast''. This\n" + " decreases gperf's running time at the cost of\n" + " minimizing generated table size. The numeric\n" + " argument represents the number of times to iterate\n" + " when resolving a collision. `0' means ``iterate by\n" + " the number of keywords''.\n" + " -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" + " -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" + " -n, --no-strlen Do not include the length of the keyword when\n" + " computing the hash function.\n" + " -o, --occurrence-sort Reorders input keys by frequency of occurrence of\n" + " the key sets. This should decrease the search time\n" + " dramatically.\n" + " -r, --random Utilizes randomness to initialize the associated\n" + " values table.\n" + " -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 -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" + "\n" + "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" + "\n" + "Report bugs to .\n" + , program_name, MAX_KEY_POS - 1, DEFAULT_JUMP_VALUE); +} + +/* Output command-line Options. */ + +void +Options::print_options (void) +{ + T (Trace t ("Options::print_options");) + int i; + + printf ("/* Command-line: "); + + for (i = 0; i < argument_count; i++) + printf ("%s ", argument_vector[i]); + + printf (" */"); +} + +/* Sorts the key positions *IN REVERSE ORDER!!* + This makes further routines more efficient. Especially when generating code. + Uses a simple Insertion Sort since the set is probably ordered. + Returns 1 if there are no duplicates, 0 otherwise. */ + +inline int +Options::key_sort (char *base, int len) +{ + T (Trace t ("Options::key_sort");) + int i, j; + + for (i = 0, j = len - 1; i < j; i++) + { + int curr, tmp; + + for (curr = i + 1,tmp = base[curr]; curr > 0 && tmp >= base[curr - 1]; curr--) + if ((base[curr] = base[curr - 1]) == tmp) /* oh no, a duplicate!!! */ + return 0; + + base[curr] = tmp; + } + + return 1; +} + +/* Sets the default Options. */ + +Options::Options (void) +{ + T (Trace t ("Options::Options");) + key_positions[0] = WORD_START; + key_positions[1] = WORD_END; + key_positions[2] = EOS; + total_keysig_size = 2; + delimiters = DEFAULT_DELIMITERS; + jump = DEFAULT_JUMP_VALUE; + option_word = DEFAULTCHARS | C; + function_name = DEFAULT_NAME; + key_name = DEFAULT_KEY; + hash_name = DEFAULT_HASH_NAME; + wordlist_name = DEFAULT_WORDLIST_NAME; + class_name = DEFAULT_CLASS_NAME; + total_switches = size = 1; + initial_asso_value = iterations = 0; +} + +/* Dumps option status when debug is set. */ + +Options::~Options (void) +{ + T (Trace t ("Options::~Options");) + if (option_word & DEBUG) + { + char *ptr; + + fprintf (stderr, "\ndumping Options:" + "\nDEBUG is.......: %s" + "\nORDER is.......: %s" + "\nTYPE is........: %s" + "\nRANDOM is......: %s" + "\nDEFAULTCHARS is: %s" + "\nSWITCH is......: %s" + "\nNOLENGTH is....: %s" + "\nLENTABLE is....: %s" + "\nDUP is.........: %s" + "\nFAST is........: %s" + "\nCOMP is........: %s" + "\nNOTYPE is......: %s" + "\nGLOBAL is......: %s" + "\nCONST is.......: %s" + "\nKRC is.........: %s" + "\nC is...........: %s" + "\nANSIC is.......: %s" + "\nCPLUSPLUS is...: %s" + "\nENUM is........: %s" + "\nINCLUDE is.....: %s" + "\nSEVENBIT is....: %s" + "\niterations = %d" + "\nlookup function name = %s" + "\nhash function name = %s" + "\nword list name = %s" + "\nkey name = %s" + "\njump value = %d" + "\nmax associated value = %d" + "\ninitial associated value = %d" + "\ndelimiters = %s" + "\nnumber of switch statements = %d\n", + option_word & DEBUG ? "enabled" : "disabled", + option_word & ORDER ? "enabled" : "disabled", + option_word & TYPE ? "enabled" : "disabled", + option_word & RANDOM ? "enabled" : "disabled", + option_word & DEFAULTCHARS ? "enabled" : "disabled", + option_word & SWITCH ? "enabled" : "disabled", + option_word & NOLENGTH ? "enabled" : "disabled", + option_word & LENTABLE ? "enabled" : "disabled", + option_word & DUP ? "enabled" : "disabled", + option_word & FAST ? "enabled" : "disabled", + option_word & COMP ? "enabled" : "disabled", + option_word & NOTYPE ? "enabled" : "disabled", + option_word & GLOBAL ? "enabled" : "disabled", + option_word & CONST ? "enabled" : "disabled", + option_word & KRC ? "enabled" : "disabled", + option_word & C ? "enabled" : "disabled", + option_word & ANSIC ? "enabled" : "disabled", + option_word & CPLUSPLUS ? "enabled" : "disabled", + option_word & ENUM ? "enabled" : "disabled", + option_word & INCLUDE ? "enabled" : "disabled", + option_word & SEVENBIT ? "enabled" : "disabled", + iterations, + function_name, hash_name, wordlist_name, key_name, + jump, size - 1, initial_asso_value, delimiters, total_switches); + if (option_word & ALLCHARS) + fprintf (stderr, "all characters are used in the hash function\n"); + + fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n", + total_keysig_size); + + for (ptr = key_positions; *ptr != EOS; ptr++) + if (*ptr == WORD_END) + fprintf (stderr, "$\n"); + else + fprintf (stderr, "%d\n", *ptr); + + fprintf (stderr, "finished dumping Options\n"); + } +} + + +/* Parses the command line Options and sets appropriate flags in option_word. */ + +static const struct option long_options[] = +{ + { "delimiters", required_argument, 0, 'e' }, + { "struct-type", no_argument, 0, 't' }, + { "language", required_argument, 0, 'L' }, + { "slot-name", required_argument, 0, 'K' }, + { "hash-fn-name", required_argument, 0, 'H' }, + { "lookup-fn-name", required_argument, 0, 'N' }, + { "class-name", required_argument, 0, 'Z' }, + { "seven-bit", no_argument, 0, '7' }, + { "compare-strncmp", no_argument, 0, 'c' }, + { "readonly-tables", no_argument, 0, 'C' }, + { "enum", no_argument, 0, 'E' }, + { "includes", no_argument, 0, 'I' }, + { "global", no_argument, 0, 'G' }, + { "word-array-name", required_argument, 0, 'W' }, + { "switch", required_argument, 0, 'S' }, + { "omit-struct-type", no_argument, 0, 'T' }, + { "key-positions", required_argument, 0, 'k' }, + { "compare-strlen", no_argument, 0, 'l' }, + { "duplicates", no_argument, 0, 'D' }, + { "fast", required_argument, 0, 'f' }, + { "initial-asso", required_argument, 0, 'i' }, + { "jump", required_argument, 0, 'j' }, + { "no-strlen", no_argument, 0, 'n' }, + { "occurrence-sort", no_argument, 0, 'o' }, + { "random", no_argument, 0, 'r' }, + { "size-multiple", required_argument, 0, 's' }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "debug", no_argument, 0, 'd' }, + { 0, no_argument, 0, 0 } +}; + +void +Options::operator() (int argc, char *argv[]) +{ + T (Trace t ("Options::operator()");) + int option_char; + + program_name = argv[0]; + argument_count = argc; + argument_vector = argv; + + while ((option_char = + getopt_long (argument_count, argument_vector, + "adcCDe:Ef:gGhH:i:Ij:k:K:lL:nN:oprs:S:tTvW:Z:7", + long_options, (int *)0)) + != -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': /* Allows user to provide keyword/attribute separator */ + { + option.delimiters = /*getopt*/optarg; + break; + } + case 'E': + { + option_word |= ENUM; + break; + } + case 'f': /* Generate the hash table ``fast.'' */ + { + option_word |= FAST; + if ((iterations = atoi (/*getopt*/optarg)) < 0) + { + fprintf (stderr, "iterations value must not be negative, assuming 0\n"); + iterations = 0; + } + 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. */ + { + const int BAD_VALUE = -1; + int value; + Iterator expand (/*getopt*/optarg, 1, MAX_KEY_POS - 1, WORD_END, BAD_VALUE, EOS); + + if (/*getopt*/optarg [0] == '*') /* Use all the characters for hashing!!!! */ + option_word = (option_word & ~DEFAULTCHARS) | ALLCHARS; + else + { + char *key_pos; + + for (key_pos = key_positions; (value = expand ()) != EOS; key_pos++) + if (value == BAD_VALUE) + { + fprintf (stderr, "Illegal key value or range, use 1,2,3-%d,'$' or '*'.\n", + MAX_KEY_POS - 1); + short_usage (stderr); + exit (1); + } + else + *key_pos = value;; + + *key_pos = EOS; + + if (! (total_keysig_size = (key_pos - key_positions))) + { + fprintf (stderr, "No keys selected.\n"); + short_usage (stderr); + exit (1); + } + else if (! key_sort (key_positions, total_keysig_size)) + { + fprintf (stderr, "Duplicate keys selected\n"); + short_usage (stderr); + exit (1); + } + + if (total_keysig_size != 2 + || (key_positions[0] != 1 || key_positions[1] != WORD_END)) + option_word &= ~DEFAULTCHARS; + } + break; + } + case 'K': /* Make this the keyname for the keyword component field. */ + { + key_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. */ + { + option_word &= ~(KRC | C | ANSIC | CPLUSPLUS); + if (!strcmp (/*getopt*/optarg, "KR-C")) + option_word |= KRC; + else if (!strcmp (/*getopt*/optarg, "C")) + option_word |= C; + else if (!strcmp (/*getopt*/optarg, "ANSI-C")) + option_word |= ANSIC; + else if (!strcmp (/*getopt*/optarg, "C++")) + option_word |= CPLUSPLUS; + else + { + fprintf (stderr, "unsupported language option %s, defaulting to C\n", /*getopt*/optarg); + option_word |= C; + } + 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. */ + { + option_word |= ORDER; + break; + } + case 'p': /* Generated lookup function a pointer instead of int. */ + break; /* This is now the default. */ + case 'r': /* Utilize randomness to initialize the associated values table. */ + { + option_word |= RANDOM; + if (option.initial_asso_value != 0) + fprintf (stderr, "warning, -r option superceeds -i, disabling -i option and continuing\n"); + break; + } + case 's': /* Range of associated values, determines size of final table. */ + { + if (abs (size = atoi (/*getopt*/optarg)) > 50) + fprintf (stderr, "%d is excessive, did you really mean this?! (try `%s --help' for help)\n", size, program_name); + break; + } + case 'S': /* Generate switch statement output, rather than lookup table. */ + { + option_word |= SWITCH; + if ((option.total_switches = atoi (/*getopt*/optarg)) <= 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); + 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; + Vectors::ALPHA_SIZE = 128; + break; + } + default: + short_usage (stderr); + exit (1); + } + + } + + if (argv[/*getopt*/optind] && ! freopen (argv[/*getopt*/optind], "r", stdin)) + { + fprintf (stderr, "Cannot open keyword file `%s'\n", argv[/*getopt*/optind]); + short_usage (stderr); + exit (1); + } + + 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/src/options.h b/src/options.h new file mode 100644 index 0000000..a81afe6 --- /dev/null +++ b/src/options.h @@ -0,0 +1,157 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Handles parsing the Options provided to the user. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +/* This module provides a uniform interface to the various options available + to a user of the gperf hash function generator. In addition to the + run-time options, found in the Option_Type below, there is also the + hash table Size and the Keys to be used in the hashing. + The overall design of this module was an experiment in using C++ + classes as a mechanism to enhance centralization of option and + and error handling, which tend to get out of hand in a C program. */ + +#ifndef options_h +#define options_h 1 + +#include + +/* Enumerate the potential debugging Options. */ + +enum Option_Type +{ + DEBUG = 01, /* Enable debugging (prints diagnostics to stderr). */ + ORDER = 02, /* Apply ordering heuristic to speed-up search time. */ + ALLCHARS = 04, /* Use all characters in hash function. */ + TYPE = 010, /* Handle user-defined type structured keyword input. */ + RANDOM = 020, /* Randomly initialize the associated values table. */ + DEFAULTCHARS = 040, /* Make default char positions be 1,$ (end of keyword). */ + SWITCH = 0100, /* Generate switch output to save space. */ + NOLENGTH = 0200, /* Don't include keyword length in hash computations. */ + LENTABLE = 0400, /* Generate a length table for string comparison. */ + DUP = 01000, /* Handle duplicate hash values for keywords. */ + FAST = 02000, /* Generate the hash function ``fast.'' */ + NOTYPE = 04000, /* Don't include user-defined type definition in output -- it's already defined elsewhere. */ + COMP = 010000, /* Generate strncmp rather than strcmp. */ + GLOBAL = 020000, /* Make the keyword table a global variable. */ + CONST = 040000, /* Make the generated tables readonly (const). */ + KRC = 0100000, /* Generate K&R C code: no prototypes, no const. */ + C = 0200000, /* Generate C code: no prototypes, but const (user can #define it away). */ + ANSIC = 0400000, /* Generate ISO/ANSI C code: prototypes and const, but no class. */ + CPLUSPLUS = 01000000, /* Generate C++ code: prototypes, const, class, inline, enum. */ + ENUM = 02000000, /* Use enum for constants. */ + INCLUDE = 04000000, /* Generate #include statements. */ + SEVENBIT = 010000000 /* Assume 7-bit, not 8-bit, characters. */ +}; + +/* Define some useful constants (these don't really belong here, but I'm + not sure where else to put them!). These should be consts, but g++ + doesn't seem to do the right thing with them at the moment... ;-( */ + +enum +{ + MAX_KEY_POS = 128 - 1, /* Max size of each word's key set. */ + WORD_START = 1, /* Signals the start of a word. */ + WORD_END = 0, /* Signals the end of a word. */ + EOS = MAX_KEY_POS /* Signals end of the key list. */ +}; + +/* Class manager for gperf program Options. */ + +class Options +{ +public: + Options (void); + ~Options (void); + int operator[] (Option_Type option); + void operator() (int argc, char *argv[]); + void operator= (enum Option_Type); + void operator!= (enum Option_Type); + static void print_options (void); + static void set_asso_max (int r); + static int get_asso_max (void); + static void reset (void); + static int get (void); + static int get_iterations (void); + static int get_max_keysig_size (void); + static void set_keysig_size (int); + static int get_jump (void); + static int initial_value (void); + static int get_total_switches (void); + static const char *get_function_name (void); + static const char *get_key_name (void); + static const char *get_class_name (void); + static const char *get_hash_name (void); + static const char *get_wordlist_name (void); + static const char *get_delimiter (void); + +private: + static int option_word; /* Holds the user-specified Options. */ + static int total_switches; /* Number of switch statements to generate. */ + static int total_keysig_size; /* Total number of distinct key_positions. */ + static int size; /* Range of the hash table. */ + static int key_pos; /* Tracks current key position for Iterator. */ + static int jump; /* Jump length when trying alternative values. */ + static int initial_asso_value; /* Initial value for asso_values table. */ + static int argument_count; /* Records count of command-line arguments. */ + static int iterations; /* Amount to iterate when a collision occurs. */ + static char **argument_vector; /* Stores a pointer to command-line vector. */ + static const char *function_name; /* Names used for generated lookup function. */ + static const char *key_name; /* Name used for keyword key. */ + static const char *class_name; /* Name used for generated C++ class. */ + static const char *hash_name; /* Name used for generated hash function. */ + static const char *wordlist_name; /* Name used for hash table array. */ + static const char *delimiters; /* Separates keywords from other attributes. */ + static char key_positions[MAX_KEY_POS]; /* Contains user-specified key choices. */ + static int key_sort (char *base, int len); /* Sorts key positions in REVERSE order. */ + static void short_usage (FILE * strm); /* Prints proper program usage. */ + static void long_usage (FILE * strm); /* Prints proper program usage. */ +}; + +/* Global option coordinator for the entire program. */ +extern Options option; + +/* Set to 1 if your want to stack-allocate some large arrays. + This requires compiler support for variable-size arrays on the stack + (not ANSI). */ +#ifndef LARGE_STACK_ARRAYS +#if defined(__GNUG__) && !defined(__STRICT_ANSI__) +#define LARGE_STACK_ARRAYS 1 +#else +#define LARGE_STACK_ARRAYS 0 +#endif +#endif + +/* Set to 1 if the stack is large enough for holding a text line. */ +#ifndef LARGE_STACK +#define LARGE_STACK 1 +#endif + +#ifdef __OPTIMIZE__ + +#include "trace.h" +#define INLINE inline +#include "options.icc" +#undef INLINE + +#endif + +#endif diff --git a/src/options.icc b/src/options.icc new file mode 100644 index 0000000..0d9668f --- /dev/null +++ b/src/options.icc @@ -0,0 +1,175 @@ +/* Inline Functions for options.{h,cc}. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +// This needs: +//#include "trace.h" + +/* TRUE if option enable, else FALSE. */ +INLINE int +Options::operator[] (Option_Type option) +{ + T (Trace t ("Options::operator[]");) + return option_word & option; +} + +/* Enables option OPT. */ +INLINE void +Options::operator = (enum Option_Type opt) +{ + T (Trace t ("Options::operator=");) + option_word |= opt; +} + +/* Disables option OPT. */ +INLINE void +Options::operator != (enum Option_Type opt) +{ + T (Trace t ("Options::operator!=");) + option_word &= ~opt; +} + +/* Initializes the key Iterator. */ +INLINE void +Options::reset (void) +{ + T (Trace t ("Options::reset");) + key_pos = 0; +} + +/* Returns current key_position and advance index. */ +INLINE int +Options::get (void) +{ + T (Trace t ("Options::get");) + return key_positions[key_pos++]; +} + +/* Sets the size of the table size. */ +INLINE void +Options::set_asso_max (int r) +{ + T (Trace t ("Options::set_asso_max");) + size = r; +} + +/* Returns the size of the table size. */ +INLINE int +Options::get_asso_max (void) +{ + T (Trace t ("Options::get_asso_max");) + return size; +} + +/* Returns total distinct key positions. */ +INLINE int +Options::get_max_keysig_size (void) +{ + T (Trace t ("Options::get_max_keysig_size");) + return total_keysig_size; +} + +/* Sets total distinct key positions. */ +INLINE void +Options::set_keysig_size (int size) +{ + T (Trace t ("Options::set_keysig_size");) + total_keysig_size = size; +} + +/* Returns the jump value. */ +INLINE int +Options::get_jump (void) +{ + T (Trace t ("Options::get_jump");) + return jump; +} + +/* Returns the generated function name. */ +INLINE const char * +Options::get_function_name (void) +{ + T (Trace t ("Options::get_function_name");) + return function_name; +} + +/* Returns the keyword key name. */ +INLINE const char * +Options::get_key_name (void) +{ + T (Trace t ("Options::get_key_name");) + return key_name; +} + +/* Returns the hash function name. */ +INLINE const char * +Options::get_hash_name (void) +{ + T (Trace t ("Options::get_hash_name");) + return hash_name; +} + +/* Returns the hash table array name. */ +INLINE const char * +Options::get_wordlist_name (void) +{ + T (Trace t ("Options::get_wordlist_name");) + return wordlist_name; +} + +/* Returns the generated class name. */ +INLINE const char * +Options::get_class_name (void) +{ + T (Trace t ("Options::get_class_name");) + return class_name; +} + +/* Returns the initial associated character value. */ +INLINE int +Options::initial_value (void) +{ + T (Trace t ("Options::initial_value");) + return initial_asso_value; +} + +/* Returns the iterations value. */ +INLINE int +Options::get_iterations (void) +{ + T (Trace t ("Options::get_iterations");) + return iterations; +} + +/* Returns the string used to delimit keywords from other attributes. */ +INLINE const char * +Options::get_delimiter () +{ + T (Trace t ("Options::get_delimiter");) + return delimiters; +} + +/* Gets the total number of switch statements to generate. */ +INLINE int +Options::get_total_switches () +{ + T (Trace t ("Options::get_total_switches");) + return total_switches; +} diff --git a/src/read-line.cc b/src/read-line.cc new file mode 100644 index 0000000..8cb0971 --- /dev/null +++ b/src/read-line.cc @@ -0,0 +1,97 @@ +/* Correctly reads an arbitrarily size string. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "read-line.h" + +#include +#include /* declares memcpy() */ +#include "options.h" +#include "trace.h" + +/* Recursively fills up the buffer. */ + +#define CHUNK_SIZE 4096 + +/* CHUNKS is the number of chunks (each of size CHUNK_SIZE) which have + already been read and which are temporarily stored on the stack. + This function reads the remainder of the line, allocates a buffer + for the entire line, fills the part beyond &buffer[chunks*CHUNK_SIZE], + and returns &buffer[chunks*CHUNK_SIZE]. */ + +char * +Read_Line::readln_aux (int chunks) +{ + T (Trace t ("Read_Line::readln_aux");) +#if LARGE_STACK + char buf[CHUNK_SIZE]; +#else + // Note: we don't use new, because that invokes a custom operator new. + char *buf = (char*)malloc(CHUNK_SIZE); + if (buf == NULL) + abort (); +#endif + char *bufptr = buf; + char *ptr; + int c; + + while (c = getc (fp), c != EOF && c != '\n') /* fill the current buffer */ + { + *bufptr++ = c; + if (bufptr - buf == CHUNK_SIZE) + { + if ((ptr = readln_aux (chunks + 1)) != NULL) + + /* prepend remainder to ptr buffer */ + { + ptr -= CHUNK_SIZE; + memcpy (ptr, buf, CHUNK_SIZE); + } + + goto done; + } + } + if (c == EOF && bufptr == buf && chunks == 0) + ptr = NULL; + else + { + size_t s1 = chunks * CHUNK_SIZE; + size_t s2 = bufptr - buf; + + ptr = new char[s1+s2+1]; + ptr += s1; + ptr[s2] = '\0'; + memcpy (ptr, buf, s2); + } + done: +#if !LARGE_STACK + free (buf); +#endif + + return ptr; +} + +#ifndef __OPTIMIZE__ + +#define INLINE /* not inline */ +#include "read-line.icc" +#undef INLINE + +#endif /* not defined __OPTIMIZE__ */ diff --git a/src/read-line.h b/src/read-line.h new file mode 100644 index 0000000..b243c84 --- /dev/null +++ b/src/read-line.h @@ -0,0 +1,53 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Reads arbitrarily long string from input file, returning it as a + dynamically allocated buffer. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +/* Returns a pointer to an arbitrary length string. Returns NULL on error or EOF + The storage for the string is dynamically allocated by new. */ + +#ifndef read_line_h +#define read_line_h 1 + +#include + +class Read_Line +{ +private: + char *readln_aux (int chunks); + FILE *fp; /* FILE pointer to the input stream. */ + +public: + Read_Line (FILE *stream = stdin) : fp (stream) {} + char *get_line (void); +}; + +#ifdef __OPTIMIZE__ + +#include "trace.h" +#define INLINE inline +#include "read-line.icc" +#undef INLINE + +#endif + +#endif diff --git a/src/read-line.icc b/src/read-line.icc new file mode 100644 index 0000000..cdb5bf6 --- /dev/null +++ b/src/read-line.icc @@ -0,0 +1,47 @@ +/* Inline Functions for read-line.{h,cc}. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +// This needs: +//#include +//#include "trace.h" + +/* Returns the ``next'' line, ignoring comments beginning with '#'. */ +INLINE char * +Read_Line::get_line (void) +{ + T (Trace t ("Read_Line::get_line");) + int c; + + while ((c = getc (fp)) == '#') + { + while (c = getc (fp), c != EOF && c != '\n') + ; + + if (c == EOF) + return (char *)0; + } + + if (c == EOF) + return (char *)0; + + ungetc (c, stdin); + return readln_aux (0); +} diff --git a/src/trace.cc b/src/trace.cc new file mode 100644 index 0000000..e571aba --- /dev/null +++ b/src/trace.cc @@ -0,0 +1,35 @@ +/* Tracing function calls. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "trace.h" + +#include + +int Trace::nesting = 0; + +Trace::Trace (const char *n) +{ + fprintf (stderr, "%*scalling %s\n", 3 * nesting++, "", name = n); +} + +Trace::~Trace (void) +{ + fprintf (stderr, "%*sleaving %s\n", 3 * --nesting, "", name); +} diff --git a/src/trace.h b/src/trace.h new file mode 100644 index 0000000..f16fcc5 --- /dev/null +++ b/src/trace.h @@ -0,0 +1,40 @@ +/* Tracing function calls. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef trace_h +#define trace_h 1 + +#ifdef TRACE +#define T(X) X +#else +#define T(X) +#endif + +class Trace +{ +private: + static int nesting; + const char *name; +public: + Trace (const char *n); + ~Trace (void); +}; + +#endif diff --git a/src/vectors.cc b/src/vectors.cc new file mode 100644 index 0000000..1da014d --- /dev/null +++ b/src/vectors.cc @@ -0,0 +1,25 @@ +/* Static class data members that are shared between several classes. + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "vectors.h" + +int Vectors::ALPHA_SIZE = MAX_ALPHA_SIZE; +int Vectors::occurrences[MAX_ALPHA_SIZE]; +int Vectors::asso_values[MAX_ALPHA_SIZE]; diff --git a/src/vectors.h b/src/vectors.h new file mode 100644 index 0000000..28a1053 --- /dev/null +++ b/src/vectors.h @@ -0,0 +1,37 @@ +/* This may look like C code, but it is really -*- C++ -*- */ + +/* Static class data members that are shared between several classes via + inheritance. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef vectors_h +#define vectors_h 1 + +static const int MAX_ALPHA_SIZE = 256; + +struct Vectors +{ + static int ALPHA_SIZE; /* Size of alphabet. */ + static int occurrences[MAX_ALPHA_SIZE]; /* Counts occurrences of each key set character. */ + static int asso_values[MAX_ALPHA_SIZE]; /* Value associated with each character. */ +}; + +#endif diff --git a/src/version.cc b/src/version.cc new file mode 100644 index 0000000..2e5cf68 --- /dev/null +++ b/src/version.cc @@ -0,0 +1,22 @@ +/* Current program version number. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +const char *version_string = "2.7"; diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..4ffba2e --- /dev/null +++ b/src/version.h @@ -0,0 +1,23 @@ +/* Current program version number. + + Copyright (C) 1989-1998 Free Software Foundation, Inc. + written by Douglas C. Schmidt (schmidt@ics.uci.edu) + +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +/* Current release version. */ +extern const char *version_string; diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..a7e3be0 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,232 @@ +# Makefile for gperf/tests + +# Copyright (C) 1989, 1992, 1993, 1995, 1998 Free Software Foundation, Inc. +# written by Douglas C. Schmidt (schmidt@ics.uci.edu) +# +# 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 1, 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 GNU GPERF; see the file COPYING. If not, write to the Free +# Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +# Other +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +VPATH = $(srcdir) + +GPERF = ../src/gperf + +all : + +install : all + +installdirs : + +uninstall : + +check : check-link-c check-link-c++ check-c check-ada check-modula3 check-pascal check-test + @true + +extracheck : @CHECK_LANG_SYNTAX@ + @true + +check-link-c: force + @echo "performing some tests of the perfect hash generator" + $(CC) -c $(CFLAGS) $(srcdir)/test.c + $(GPERF) -p -c -l -S1 -o $(srcdir)/c.gperf > cinset.c + $(CC) $(CFLAGS) -o cout cinset.c test.o + +check-link-c++: force + +check-c: + @echo "testing ANSI C reserved words, all items should be found in the set" + ./cout -v < $(srcdir)/c.gperf > c.out + diff $(srcdir)/c.exp c.out + +check-ada: + $(GPERF) -k1,4,'$$' $(srcdir)/ada.gperf > adainset.c +# double '$$' is only there since make gets confused; program wants only 1 '$' + $(CC) $(CFLAGS) -o aout adainset.c test.o + @echo "testing Ada reserved words, all items should be found in the set" + ./aout -v < $(srcdir)/ada.gperf > ada-res.out + diff $(srcdir)/ada-res.exp ada-res.out + $(GPERF) -p -D -k1,'$$' -s 2 -o $(srcdir)/adadefs.gperf > preinset.c + $(CC) $(CFLAGS) -o preout preinset.c test.o + @echo "testing Ada predefined words, all items should be found in the set" + ./preout -v < $(srcdir)/adadefs.gperf > ada-pred.out + diff $(srcdir)/ada-pred.exp ada-pred.out + +check-modula3: + $(GPERF) -k1,2,'$$' -o $(srcdir)/modula3.gperf > m3inset.c + $(CC) $(CFLAGS) -o m3out m3inset.c test.o + @echo "testing Modula3 reserved words, all items should be found in the set" + ./m3out -v < $(srcdir)/modula3.gperf > modula.out + diff $(srcdir)/modula.exp modula.out + +check-pascal: + $(GPERF) -o -S2 -p < $(srcdir)/pascal.gperf > pinset.c + $(CC) $(CFLAGS) -o pout pinset.c test.o + @echo "testing Pascal reserved words, all items should be found in the set" + ./pout -v < $(srcdir)/pascal.gperf > pascal.out + diff $(srcdir)/pascal.exp pascal.out + +# these next 5 are demos that show off the generated code +check-test: + $(GPERF) -p -j1 -g -o -t -N is_reserved_word -k1,3,'$$' < $(srcdir)/c-parse.gperf > test-1.out + diff $(srcdir)/test-1.exp test-1.out + $(GPERF) -n -k1-8 -l < $(srcdir)/modula2.gperf > test-2.out + diff $(srcdir)/test-2.exp test-2.out + $(GPERF) -p -j 1 -o -a -C -g -t -k1,4,$$ < $(srcdir)/gplus.gperf > test-3.out + diff $(srcdir)/test-3.exp test-3.out + $(GPERF) -D -p -t < $(srcdir)/c-parse.gperf > test-4.out + diff $(srcdir)/test-4.exp test-4.out + $(GPERF) -g -o -j1 -t -p -N is_reserved_word < $(srcdir)/gpc.gperf > test-5.out + diff $(srcdir)/test-5.exp test-5.out +# prints out the help message + -$(GPERF) -h > test-6.out 2>&1 + diff $(srcdir)/test-6.exp test-6.out + @echo "only if, do, for, case, goto, else, while, and return should be found " + ./aout -v < $(srcdir)/c.gperf > test-7.out + diff $(srcdir)/test-7.exp test-7.out + +# The following validates valid language syntax with different parameters. +# Works only with gcc and g++, and only on platforms where "gcc -ansi" is +# usable. (There are still platforms where gcc-2.8.0's fixincludes does not +# work well enough.) + +VALIDATE = CC='$(CC)' CFLAGS='$(CFLAGS)' CXX='$(CXX)' CXXFLAGS='$(CXXFLAGS)' GPERF='$(GPERF)' ./validate + +check-lang-syntax : force + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -G -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -G -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -S 1000 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -S 10 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -S 10 -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -S 10 -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -p -S 1000 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -K key_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -H hash_function_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest1.gperf -W word_list_name + sed -e 's,in_word_set,lookup_function_name,g' < jstest1.gperf > tmp-jstest1.gperf && \ + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest1.gperf -N lookup_function_name + sed -e 's,Perfect_Hash,class_name,g' < jstest1.gperf > tmp-jstest1.gperf && \ + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest1.gperf -Z class_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -G -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -G -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -S 1000 + sed -e 's,name,key_name,g' < jstest2.gperf > tmp-jstest2.gperf && \ + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -p -K key_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 jstest2.gperf -t -p -H hash_function_name + sed -e 's,in_word_set,lookup_function_name,g' < jstest2.gperf > tmp-jstest2.gperf && \ + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -p -N lookup_function_name + sed -e 's,Perfect_Hash,class_name,g' < jstest2.gperf > tmp-jstest2.gperf && \ + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -p -Z class_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -c + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -G + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -G -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -G -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -D + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -D -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -c + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -G + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -D + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 10 -D -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -S 1000 + sed -e 's,name,key_name,g' < jstest3.gperf > tmp-jstest3.gperf && \ + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -p -K key_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 jstest3.gperf -t -p -H hash_function_name + sed -e 's,in_word_set,lookup_function_name,g' < jstest3.gperf > tmp-jstest3.gperf && \ + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -p -N lookup_function_name + sed -e 's,Perfect_Hash,class_name,g' < jstest3.gperf > tmp-jstest3.gperf && \ + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -p -Z class_name + +mostlyclean : clean + +clean : force + $(RM) *.o core *inset.c output.* *.out aout cout m3out pout preout tmp-* valitest* + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + +force : + diff --git a/tests/ada-pred.exp b/tests/ada-pred.exp new file mode 100644 index 0000000..33caaa3 --- /dev/null +++ b/tests/ada-pred.exp @@ -0,0 +1,54 @@ +in word set boolean +in word set character +in word set constraint_error +in word set false +in word set float +in word set integer +in word set natural +in word set numeric_error +in word set positive +in word set program_error +in word set storage_error +in word set string +in word set tasking_error +in word set true +in word set address +in word set aft +in word set base +in word set callable +in word set constrained +in word set count +in word set delta +in word set digits +in word set emax +in word set epsilon +in word set first +in word set firstbit +in word set fore +in word set image +in word set large +in word set last +in word set lastbit +in word set length +in word set machine_emax +in word set machine_emin +in word set machine_mantissa +in word set machine_overflows +in word set machine_radix +in word set machine_rounds +in word set mantissa +in word set pos +in word set position +in word set pred +in word set range +in word set safe_emax +in word set safe_large +in word set safe_small +in word set size +in word set small +in word set storage_size +in word set succ +in word set terminated +in word set val +in word set value +in word set width diff --git a/tests/ada-res.exp b/tests/ada-res.exp new file mode 100644 index 0000000..8134fe8 --- /dev/null +++ b/tests/ada-res.exp @@ -0,0 +1,63 @@ +in word set else +in word set exit +in word set terminate +in word set type +in word set raise +in word set range +in word set reverse +in word set declare +in word set end +in word set record +in word set exception +in word set not +in word set then +in word set return +in word set separate +in word set select +in word set digits +in word set renames +in word set subtype +in word set elsif +in word set function +in word set for +in word set package +in word set procedure +in word set private +in word set while +in word set when +in word set new +in word set entry +in word set delay +in word set case +in word set constant +in word set at +in word set abort +in word set accept +in word set and +in word set delta +in word set access +in word set abs +in word set pragma +in word set array +in word set use +in word set out +in word set do +in word set others +in word set of +in word set or +in word set all +in word set limited +in word set loop +in word set null +in word set task +in word set in +in word set is +in word set if +in word set rem +in word set mod +in word set begin +in word set body +in word set xor +in word set goto +in word set generic +in word set with diff --git a/tests/ada.gperf b/tests/ada.gperf new file mode 100644 index 0000000..332bdc7 --- /dev/null +++ b/tests/ada.gperf @@ -0,0 +1,63 @@ +else +exit +terminate +type +raise +range +reverse +declare +end +record +exception +not +then +return +separate +select +digits +renames +subtype +elsif +function +for +package +procedure +private +while +when +new +entry +delay +case +constant +at +abort +accept +and +delta +access +abs +pragma +array +use +out +do +others +of +or +all +limited +loop +null +task +in +is +if +rem +mod +begin +body +xor +goto +generic +with diff --git a/tests/adadefs.gperf b/tests/adadefs.gperf new file mode 100644 index 0000000..875be69 --- /dev/null +++ b/tests/adadefs.gperf @@ -0,0 +1,54 @@ +boolean +character +constraint_error +false +float +integer +natural +numeric_error +positive +program_error +storage_error +string +tasking_error +true +address +aft +base +callable +constrained +count +delta +digits +emax +epsilon +first +firstbit +fore +image +large +last +lastbit +length +machine_emax +machine_emin +machine_mantissa +machine_overflows +machine_radix +machine_rounds +mantissa +pos +position +pred +range +safe_emax +safe_large +safe_small +size +small +storage_size +succ +terminated +val +value +width diff --git a/tests/c++.gperf b/tests/c++.gperf new file mode 100644 index 0000000..650d32d --- /dev/null +++ b/tests/c++.gperf @@ -0,0 +1,47 @@ +asm +auto +break +case +catch +char +class +const +continue +default +delete +do +double +else +enum +extern +float +for +friend +goto +if +inline +int +long +new +operator +overload +private +protected +public +register +return +short +signed +sizeof +static +struct +switch +template +this +typedef +union +unsigned +virtual +void +volatile +while diff --git a/tests/c-parse.gperf b/tests/c-parse.gperf new file mode 100644 index 0000000..d11788c --- /dev/null +++ b/tests/c-parse.gperf @@ -0,0 +1,56 @@ +%{ +/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ +%} +struct resword { char *name; short token; enum rid rid; }; +%% +__alignof, ALIGNOF, NORID +__alignof__, ALIGNOF, NORID +__asm, ASM, NORID +__asm__, ASM, NORID +__attribute, ATTRIBUTE, NORID +__attribute__, ATTRIBUTE, NORID +__const, TYPE_QUAL, RID_CONST +__const__, TYPE_QUAL, RID_CONST +__inline, SCSPEC, RID_INLINE +__inline__, SCSPEC, RID_INLINE +__signed, TYPESPEC, RID_SIGNED +__signed__, TYPESPEC, RID_SIGNED +__typeof, TYPEOF, NORID +__typeof__, TYPEOF, NORID +__volatile, TYPE_QUAL, RID_VOLATILE +__volatile__, TYPE_QUAL, RID_VOLATILE +asm, ASM, NORID +auto, SCSPEC, RID_AUTO +break, BREAK, NORID +case, CASE, NORID +char, TYPESPEC, RID_CHAR +const, TYPE_QUAL, RID_CONST +continue, CONTINUE, NORID +default, DEFAULT, NORID +do, DO, NORID +double, TYPESPEC, RID_DOUBLE +else, ELSE, NORID +enum, ENUM, NORID +extern, SCSPEC, RID_EXTERN +float, TYPESPEC, RID_FLOAT +for, FOR, NORID +goto, GOTO, NORID +if, IF, NORID +inline, SCSPEC, RID_INLINE +int, TYPESPEC, RID_INT +long, TYPESPEC, RID_LONG +register, SCSPEC, RID_REGISTER +return, RETURN, NORID +short, TYPESPEC, RID_SHORT +signed, TYPESPEC, RID_SIGNED +sizeof, SIZEOF, NORID +static, SCSPEC, RID_STATIC +struct, STRUCT, NORID +switch, SWITCH, NORID +typedef, SCSPEC, RID_TYPEDEF +typeof, TYPEOF, NORID +union, UNION, NORID +unsigned, TYPESPEC, RID_UNSIGNED +void, TYPESPEC, RID_VOID +volatile, TYPE_QUAL, RID_VOLATILE +while, WHILE, NORID diff --git a/tests/c.exp b/tests/c.exp new file mode 100644 index 0000000..10c8b7f --- /dev/null +++ b/tests/c.exp @@ -0,0 +1,32 @@ +in word set if +in word set do +in word set int +in word set for +in word set case +in word set char +in word set auto +in word set goto +in word set else +in word set long +in word set void +in word set enum +in word set float +in word set short +in word set union +in word set break +in word set while +in word set const +in word set double +in word set static +in word set extern +in word set struct +in word set return +in word set sizeof +in word set switch +in word set signed +in word set typedef +in word set default +in word set unsigned +in word set continue +in word set register +in word set volatile diff --git a/tests/c.gperf b/tests/c.gperf new file mode 100644 index 0000000..8672d6c --- /dev/null +++ b/tests/c.gperf @@ -0,0 +1,32 @@ +if +do +int +for +case +char +auto +goto +else +long +void +enum +float +short +union +break +while +const +double +static +extern +struct +return +sizeof +switch +signed +typedef +default +unsigned +continue +register +volatile diff --git a/tests/configure b/tests/configure new file mode 100755 index 0000000..1c715de --- /dev/null +++ b/tests/configure @@ -0,0 +1,1214 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=c-parse.gperf + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:523: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:552: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:581: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:629: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:663: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:668: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:692: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:720: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:741: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:758: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + for ac_prog in $CCC c++ g++ gcc CC cxx cc++ +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:785: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:816: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:856: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:861: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes + ac_test_CXXFLAGS="${CXXFLAGS+set}" + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS= + echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:885: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 + if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" + elif test $ac_cv_prog_cxx_g = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-O2" + fi +else + GXX= + test "${CXXFLAGS+set}" = set || CXXFLAGS="-g" +fi + + echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 +echo "configure:913: checking how to run the C++ preprocessor" >&5 +if test -z "$CXXCPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + CXXCPP="${CXX-g++} -E" + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:931: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CXXCPP=/lib/cpp +fi +rm -f conftest* + ac_cv_prog_CXXCPP="$CXXCPP" +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross +fi +fi +CXXCPP="$ac_cv_prog_CXXCPP" +echo "$ac_t""$CXXCPP" 1>&6 + + if test $ac_cv_prog_gcc = yes -a $ac_cv_prog_gxx = yes; then + CHECK_LANG_SYNTAX='check-lang-syntax' +else + CHECK_LANG_SYNTAX='' +fi + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@CXX@%$CXX%g +s%@CXXCPP@%$CXXCPP%g +s%@CHECK_LANG_SYNTAX@%$CHECK_LANG_SYNTAX%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/tests/configure.in b/tests/configure.in new file mode 100644 index 0000000..a62450d --- /dev/null +++ b/tests/configure.in @@ -0,0 +1,45 @@ +dnl autoconf configuration for gperf/tests + +dnl Copyright (C) 1998 Free Software Foundation, Inc. +dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu) +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 1, 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 GNU GPERF; see the file COPYING. If not, write to the +dnl Free Software Foundation, 59 Temple Place - Suite 330, Boston, +dnl MA 02111-1307, USA. + +AC_INIT(c-parse.gperf) +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 +if test $ac_cv_prog_gcc = yes -a $ac_cv_prog_gxx = yes; then + CHECK_LANG_SYNTAX='check-lang-syntax' +else + CHECK_LANG_SYNTAX='' +fi +AC_SUBST(CHECK_LANG_SYNTAX) +dnl +dnl That's it. +dnl +AC_OUTPUT(Makefile) diff --git a/tests/gpc.gperf b/tests/gpc.gperf new file mode 100644 index 0000000..8fb469e --- /dev/null +++ b/tests/gpc.gperf @@ -0,0 +1,48 @@ +%{ +/* ISO Pascal 7185 reserved words. + * + * For GNU Pascal compiler (GPC) by jtv@hut.fi + * + * run this through the Doug Schmidt's gperf program + * with command + * gperf -g -o -j1 -t -p -N is_reserved_word + * + */ +%} +struct resword { char *name; short token; short iclass;}; +%% +And, AND, PASCAL_ISO +Array, ARRAY, PASCAL_ISO +Begin, BEGIN_, PASCAL_ISO +Case, CASE, PASCAL_ISO +Const, CONST, PASCAL_ISO +Div, DIV, PASCAL_ISO +Do, DO, PASCAL_ISO +Downto, DOWNTO, PASCAL_ISO +Else, ELSE, PASCAL_ISO +End, END, PASCAL_ISO +File, FILE_, PASCAL_ISO +For, FOR, PASCAL_ISO +Function, FUNCTION, PASCAL_ISO +Goto, GOTO, PASCAL_ISO +If, IF, PASCAL_ISO +In, IN, PASCAL_ISO +Label, LABEL, PASCAL_ISO +Mod, MOD, PASCAL_ISO +Nil, NIL, PASCAL_ISO +Not, NOT, PASCAL_ISO +Of, OF, PASCAL_ISO +Or, OR, PASCAL_ISO +Packed, PACKED, PASCAL_ISO +Procedure, PROCEDURE, PASCAL_ISO +Program,PROGRAM,PASCAL_ISO +Record, RECORD, PASCAL_ISO +Repeat, REPEAT, PASCAL_ISO +Set, SET, PASCAL_ISO +Then, THEN, PASCAL_ISO +To, TO, PASCAL_ISO +Type, TYPE, PASCAL_ISO +Until, UNTIL, PASCAL_ISO +Var, VAR, PASCAL_ISO +While, WHILE, PASCAL_ISO +With, WITH, PASCAL_ISO diff --git a/tests/gplus.gperf b/tests/gplus.gperf new file mode 100644 index 0000000..4a93315 --- /dev/null +++ b/tests/gplus.gperf @@ -0,0 +1,76 @@ +%{ +/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ gplus.gperf */ +%} +struct resword { char *name; short token; enum rid rid;}; +%% +__alignof, ALIGNOF, NORID +__alignof__, ALIGNOF, NORID +__asm, ASM, NORID +__asm__, ASM, NORID +__attribute, ATTRIBUTE, NORID +__attribute__, ATTRIBUTE, NORID +__const, TYPE_QUAL, RID_CONST +__const__, TYPE_QUAL, RID_CONST +__inline, SCSPEC, RID_INLINE +__inline__, SCSPEC, RID_INLINE +__signed, TYPESPEC, RID_SIGNED +__signed__, TYPESPEC, RID_SIGNED +__typeof, TYPEOF, NORID +__typeof__, TYPEOF, NORID +__volatile, TYPE_QUAL, RID_VOLATILE +__volatile__, TYPE_QUAL, RID_VOLATILE +all, ALL, NORID /* Extension */, +except, EXCEPT, NORID /* Extension */, +exception, AGGR, RID_EXCEPTION /* Extension */, +raise, RAISE, NORID /* Extension */, +raises, RAISES, NORID /* Extension */, +reraise, RERAISE, NORID /* Extension */, +try, TRY, NORID /* Extension */, +asm, ASM, NORID, +auto, SCSPEC, RID_AUTO, +break, BREAK, NORID, +case, CASE, NORID, +catch, CATCH, NORID, +char, TYPESPEC, RID_CHAR, +class, AGGR, RID_CLASS, +const, TYPE_QUAL, RID_CONST, +continue, CONTINUE, NORID, +default, DEFAULT, NORID, +delete, DELETE, NORID, +do, DO, NORID, +double, TYPESPEC, RID_DOUBLE, +dynamic, DYNAMIC, NORID, +else, ELSE, NORID, +enum, ENUM, NORID, +extern, SCSPEC, RID_EXTERN, +float, TYPESPEC, RID_FLOAT, +for, FOR, NORID, +friend, SCSPEC, RID_FRIEND, +goto, GOTO, NORID, +if, IF, NORID, +inline, SCSPEC, RID_INLINE, +int, TYPESPEC, RID_INT, +long, TYPESPEC, RID_LONG, +new, NEW, NORID, +operator, OPERATOR, NORID, +overload, OVERLOAD, NORID, +private, PRIVATE, NORID, +protected, PROTECTED, NORID, +public, PUBLIC, NORID, +register, SCSPEC, RID_REGISTER, +return, RETURN, NORID, +short, TYPESPEC, RID_SHORT, +signed, TYPESPEC, RID_SIGNED, +sizeof, SIZEOF, NORID, +static, SCSPEC, RID_STATIC, +struct, AGGR, RID_RECORD, +switch, SWITCH, NORID, +this, THIS, NORID, +typedef, SCSPEC, RID_TYPEDEF, +typeof, TYPEOF, NORID, +union, AGGR, RID_UNION, +unsigned, TYPESPEC, RID_UNSIGNED, +virtual, SCSPEC, RID_VIRTUAL, +void, TYPESPEC, RID_VOID, +volatile, TYPE_QUAL, RID_VOLATILE, +while, WHILE, NORID, diff --git a/tests/irc.gperf b/tests/irc.gperf new file mode 100644 index 0000000..afe53c5 --- /dev/null +++ b/tests/irc.gperf @@ -0,0 +1,63 @@ +%{ +extern int m_text(), m_private(), m_who(), m_whois(), m_user(), m_list(); +extern int m_topic(), m_invite(), m_channel(), m_version(), m_quit(); +extern int m_server(), m_kill(), m_info(), m_links(), m_summon(), m_stats(); +extern int m_users(), m_nick(), m_error(), m_help(), m_whoreply(); +extern int m_squit(), m_restart(), m_away(), m_die(), m_connect(); +extern int m_ping(), m_pong(), m_oper(), m_pass(), m_wall(), m_trace(); +extern int m_time(), m_rehash(), m_names(), m_namreply(), m_admin(); +extern int m_linreply(), m_notice(), m_lusers(), m_voice(), m_grph(); +extern int m_xtra(), m_motd(); +%} +struct Message { + char *cmd; + int (* func)(); + int count; + int parameters; +}; +%% +NICK, m_nick, 0, 1 +MSG, m_text, 0, 1 +PRIVMSG, m_private, 0, 2 +WHO, m_who, 0, 1 +WHOIS, m_whois, 0, 4 +USER, m_user, 0, 4 +SERVER, m_server, 0, 2 +LIST, m_list, 0, 1 +TOPIC, m_topic, 0, 1 +INVITE, m_invite, 0, 2 +CHANNEL, m_channel, 0, 1 +VERSION, m_version, 0, 1 +QUIT, m_quit, 0, 2 +SQUIT, m_squit, 0, 2 +KILL, m_kill, 0, 2 +INFO, m_info, 0, 1 +LINKS, m_links, 0, 1 +SUMMON, m_summon, 0, 1 +STATS, m_stats, 0, 1 +USERS, m_users, 0, 1 +RESTART, m_restart, 0, 1 +WHOREPLY,m_whoreply, 0, 7 +HELP, m_help, 0, 2 +ERROR, m_error, 0, 1 +AWAY, m_away, 0, 1 +DIE, m_die, 0, 1 +CONNECT, m_connect, 0, 3 +PING, m_ping, 0, 2 +PONG, m_pong, 0, 3 +OPER, m_oper, 0, 3 +PASS, m_pass, 0, 2 +WALL, m_wall, 0, 1 +TIME, m_time, 0, 1 +REHASH, m_rehash, 0, 1 +NAMES, m_names, 0, 1 +NAMREPLY,m_namreply, 0, 3 +ADMIN, m_admin, 0, 1 +TRACE, m_trace, 0, 1 +LINREPLY,m_linreply, 0, 2 +NOTICE, m_notice, 0, 2 +LUSERS, m_lusers, 0, 1 +VOICE, m_voice, 0, 2 +GRPH, m_grph, 0, 2 +XTRA, m_xtra, 0, 2 +MOTD, m_motd, 0, 2 diff --git a/tests/jscript.gperf b/tests/jscript.gperf new file mode 100644 index 0000000..6f420d8 --- /dev/null +++ b/tests/jscript.gperf @@ -0,0 +1,73 @@ +%{ +/* Command-line: gperf -k'1,2,$' -t -p -K 'name' -H 'js_kw_hash' -N 'js_kw_lookup' -a -g jscript.gperf */ +%} +struct js_keyword { + char * name; + int token; +} + +%% +# Javascript reserved words, see "keywords.html" +abstract, TK_ABSTRACT +boolean, TK_BOOLEAN +break, TK_BREAK +byte, TK_BYTE +case, TK_CASE +catch, TK_CATCH +char, TK_CHAR +class, TK_CLASS +const, TK_CONST +continue, TK_CONTINUE +default, TK_DEFAULT +do, TK_DO +double, TK_DOUBLE +else, TK_ELSE +extends, TK_EXTENDS +false, TK_FALSE +final, TK_FINAL +finally, TK_FINALLY +float, TK_FLOAT +for, TK_FOR +function, TK_FUNCTION +goto, TK_GOTO +if, TK_IF +implements, TK_IMPLEMENTS +import, TK_IMPORT +in, TK_IN +instanceof, TK_INSTANCEOF +int, TK_INT +interface, TK_INTERFACE +long, TK_LONG +native, TK_NATIVE +new, TK_NEW +null, TK_NULL +package, TK_PACKAGE +private, TK_PRIVATE +protected, TK_PROTECTED +public, TK_PUBLIC +return, TK_RETURN +short, TK_SHORT +static, TK_STATIC +super, TK_SUPER +switch, TK_SWITCH +synchronized, TK_SYNCHRONIZED +this, TK_THIS +throw, TK_THROW +throws, TK_THROWS +transient, TK_TRANSIENT +true, TK_TRUE +try, TK_TRY +var, TK_VAR +void, TK_VOID +while, TK_WHILE +with, TK_WITH +%% + +int js_keyword_lookup (register const char *str, register int len) +{ + struct js_keyword * keyword = js_kw_lookup(str,len); + if (keyword) + return keyword->token; + else + return TK_IDENT; +} diff --git a/tests/jstest1.gperf b/tests/jstest1.gperf new file mode 100644 index 0000000..f6696b1 --- /dev/null +++ b/tests/jstest1.gperf @@ -0,0 +1,142 @@ +abstract +boolean +break +byte +case +catch +char +class +const +continue +default +do +double +else +extends +false +final +finally +float +for +function +goto +if +implements +import +in +instanceof +int +interface +long +native +new +null +package +private +protected +public +return +short +static +super +switch +synchronized +this +throw +throws +transient +true +try +var +void +while +with +%% +#include +#include +#if defined(__STDC__) || defined(__cplusplus) +#define CONST const +#else +#define CONST +#endif +static CONST char* testdata[] = { + "bogus", + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "var", + "void", + "while", + "with" +}; +int main () +{ + int i; + for (i = 0; i < sizeof(testdata)/sizeof(testdata[0]); i++) + { +#ifdef CPLUSPLUS_TEST + CONST char * resword = Perfect_Hash::in_word_set(testdata[i],strlen(testdata[i])); +#else + CONST char * resword = in_word_set(testdata[i],strlen(testdata[i])); +#endif + if (i > 0) + { + if (!resword) + exit (1); + if (strcmp(testdata[i],resword)) + exit (1); + } + else + { + if (resword) + exit (1); + } + } + return 0; +} diff --git a/tests/jstest2.gperf b/tests/jstest2.gperf new file mode 100644 index 0000000..ee0fa7f --- /dev/null +++ b/tests/jstest2.gperf @@ -0,0 +1,147 @@ +struct js_keyword { + char * name; + int token; +} +%% +abstract, 1 +boolean, 2 +break, 3 +byte, 4 +case, 5 +catch, 6 +char, 7 +class, 8 +const, 9 +continue, 10 +default, 11 +do, 12 +double, 13 +else, 14 +extends, 15 +false, 16 +final, 17 +finally, 18 +float, 19 +for, 20 +function, 21 +goto, 22 +if, 23 +implements, 24 +import, 25 +in, 26 +instanceof, 27 +int, 28 +interface, 29 +long, 30 +native, 31 +new, 32 +null, 33 +package, 34 +private, 35 +protected, 36 +public, 37 +return, 38 +short, 39 +static, 40 +super, 41 +switch, 42 +synchronized, 43 +this, 44 +throw, 45 +throws, 46 +transient, 47 +true, 48 +try, 49 +var, 50 +void, 51 +while, 52 +with, 53 +%% +#include +#include +#if defined(__STDC__) || defined(__cplusplus) +#define CONST const +#else +#define CONST +#endif +static CONST char* testdata[] = { + "bogus", + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "var", + "void", + "while", + "with" +}; +int main () +{ + int i; + for (i = 0; i < sizeof(testdata)/sizeof(testdata[0]); i++) + { +#ifdef CPLUSPLUS_TEST + CONST struct js_keyword * resword = Perfect_Hash::in_word_set(testdata[i],strlen(testdata[i])); +#else + CONST struct js_keyword * resword = in_word_set(testdata[i],strlen(testdata[i])); +#endif + if (i > 0) + { + if (!resword) + exit (1); + if (strcmp(testdata[i],resword->name)) + exit (1); + } + else + { + if (resword) + exit (1); + } + } + return 0; +} diff --git a/tests/jstest3.gperf b/tests/jstest3.gperf new file mode 100644 index 0000000..54d37ce --- /dev/null +++ b/tests/jstest3.gperf @@ -0,0 +1,147 @@ +struct js_keyword { + const char * name; + int token; +} +%% +abstract, 1 +boolean, 2 +break, 3 +byte, 4 +case, 5 +catch, 6 +char, 7 +class, 8 +const, 9 +continue, 10 +default, 11 +do, 12 +double, 13 +else, 14 +extends, 15 +false, 16 +final, 17 +finally, 18 +float, 19 +for, 20 +function, 21 +goto, 22 +if, 23 +implements, 24 +import, 25 +in, 26 +instanceof, 27 +int, 28 +interface, 29 +long, 30 +native, 31 +new, 32 +null, 33 +package, 34 +private, 35 +protected, 36 +public, 37 +return, 38 +short, 39 +static, 40 +super, 41 +switch, 42 +synchronized, 43 +this, 44 +throw, 45 +throws, 46 +transient, 47 +true, 48 +try, 49 +var, 50 +void, 51 +while, 52 +with, 53 +%% +#include +#include +#if defined(__STDC__) || defined(__cplusplus) +#define CONST const +#else +#define CONST +#endif +static CONST char* testdata[] = { + "bogus", + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "var", + "void", + "while", + "with" +}; +int main () +{ + int i; + for (i = 0; i < sizeof(testdata)/sizeof(testdata[0]); i++) + { +#ifdef CPLUSPLUS_TEST + CONST struct js_keyword * resword = Perfect_Hash::in_word_set(testdata[i],strlen(testdata[i])); +#else + CONST struct js_keyword * resword = in_word_set(testdata[i],strlen(testdata[i])); +#endif + if (i > 0) + { + if (!resword) + exit (1); + if (strcmp(testdata[i],resword->name)) + exit (1); + } + else + { + if (resword) + exit (1); + } + } + return 0; +} diff --git a/tests/makeinfo.gperf b/tests/makeinfo.gperf new file mode 100644 index 0000000..1488b8e --- /dev/null +++ b/tests/makeinfo.gperf @@ -0,0 +1,116 @@ +COMMAND; +%% +!, cm_force_sentence_end, false +', insert_self, false +*, cm_asterisk, false +., cm_force_sentence_end, false +:, cm_force_abbreviated_whitespace, false +?, cm_force_sentence_end, false +@, insert_self, false +TeX, cm_TeX, true +`, insert_self, false +appendix, cm_appendix, false +appendixsec, cm_appendixsec, false +appendixsubsec, cm_appendixsubsec, false +asis, cm_asis, true +b, cm_bold, true +br, cm_br, false +bullet, cm_bullet, true +bye, cm_bye, false +c, cm_comment, false +center, cm_center, false +chapter, cm_chapter, false +cindex, cm_cindex, false +cite, cm_cite, true +code, cm_code, true +comment, cm_comment, false +contents, do_nothing, false +copyright, cm_copyright, true +ctrl, cm_ctrl, true +defcodeindex, cm_defindex, false +defindex, cm_defindex, false +dfn, cm_dfn, true +display, cm_display, false +dots, cm_dots, true +emph, cm_emph, true +end, cm_end, false +enumerate, cm_enumerate, false +equiv, cm_equiv, true +error, cm_error, true +example, cm_example, false +exdent, cm_exdent, false +expansion, cm_expansion, true +file, cm_file, true +findex, cm_findex, false +format, cm_format, false +group, cm_group, false +i, cm_italic, true +iappendix, cm_appendix, false +iappendixsec, cm_appendixsec, false +iappendixsubsec, cm_appendixsubsec, false +ichapter, cm_chapter, false +ifinfo, cm_ifinfo, false +iftex, cm_iftex, false +ignore, cm_ignore, false +include, cm_include, false +inforef, cm_inforef, true +input, cm_include, false +isection, cm_section, false +isubsection, cm_subsection, false +isubsubsection, cm_subsubsection, false +item, cm_item, false +itemize, cm_itemize, false +itemx, cm_itemx, false +iunnumbered, cm_unnumbered, false +iunnumberedsec, cm_unnumberedsec, false +iunnumberedsubsec, cm_unnumberedsubsec, false +kbd, cm_kbd, true +key, cm_key, true +kindex, cm_kindex, false +lisp, cm_lisp, false +menu, cm_menu +minus, cm_minus, true +need, cm_need, false +node, cm_node, false +noindent, cm_noindent, false +page, do_nothing, false +pindex, cm_pindex, false +point, cm_point, true +print, cm_print, true +printindex, cm_printindex, false +pxref, cm_pxref, true +quotation, cm_quotation, false +r, cm_roman, true +ref, cm_xref, true +refill, cm_refill, false +result, cm_result, true +samp, cm_samp, true +sc, cm_sc, true +section, cm_section, false +setchapternewpage, cm_setchapternewpage, false +setfilename, cm_setfilename, false +settitle, cm_settitle, false +smallexample, cm_smallexample, false +sp, cm_sp, false +strong, cm_strong, true +subsection, cm_subsection, false +subsubsection, cm_subsubsection, false +summarycontents, do_nothing, false +syncodeindex, cm_synindex, false +synindex, cm_synindex, false +t, cm_title, true +table, cm_table, false +tex, cm_tex, false +tindex, cm_tindex, false +titlepage, cm_titlepage, false +unnumbered, cm_unnumbered, false +unnumberedsec, cm_unnumberedsec, false +unnumberedsubsec, cm_unnumberedsubsec, false +var, cm_var, true +vindex, cm_vindex, false +w, cm_w, true +xref, cm_xref, true +{, insert_self, false +}, insert_self, false +infoinclude, cm_infoinclude, false +footnote, cm_footnote, false diff --git a/tests/modula.exp b/tests/modula.exp new file mode 100644 index 0000000..cef7d5a --- /dev/null +++ b/tests/modula.exp @@ -0,0 +1,106 @@ +in word set AND +in word set ARRAY +in word set BEGIN +in word set BITS +in word set BY +in word set CASE +in word set CONST +in word set DIV +in word set DO +in word set ELSE +in word set ELSIF +in word set END +in word set EVAL +in word set EXCEPT +in word set EXCEPTION +in word set EXIT +in word set EXPORTS +in word set FINALLY +in word set FOR +in word set FROM +in word set IF +in word set IMPORT +in word set INTERFACE +in word set IN +in word set INLINE +in word set LOCK +in word set METHODS +in word set MOD +in word set MODULE +in word set NOT +in word set OBJECT +in word set OF +in word set OR +in word set PROCEDURE +in word set RAISES +in word set READONLY +in word set RECORD +in word set REF +in word set REPEAT +in word set RETURN +in word set SET +in word set THEN +in word set TO +in word set TRY +in word set TYPE +in word set TYPECASE +in word set UNSAFE +in word set UNTIL +in word set UNTRACED +in word set VALUE +in word set VAR +in word set WHILE +in word set WITH +in word set and +in word set array +in word set begin +in word set bits +in word set by +in word set case +in word set const +in word set div +in word set do +in word set else +in word set elsif +in word set end +in word set eval +in word set except +in word set exception +in word set exit +in word set exports +in word set finally +in word set for +in word set from +in word set if +in word set import +in word set interface +in word set in +in word set inline +in word set lock +in word set methods +in word set mod +in word set module +in word set not +in word set object +in word set of +in word set or +in word set procedure +in word set raises +in word set readonly +in word set record +in word set ref +in word set repeat +in word set return +in word set set +in word set then +in word set to +in word set try +in word set type +in word set typecase +in word set unsafe +in word set until +in word set untraced +in word set value +in word set var +in word set while +in word set with diff --git a/tests/modula2.gperf b/tests/modula2.gperf new file mode 100644 index 0000000..5ef9c75 --- /dev/null +++ b/tests/modula2.gperf @@ -0,0 +1,40 @@ +AND +ARRAY +BEGIN +BY +CASE +CONST +DEFINITION +DIV +DO +ELSE +ELSIF +END +EXIT +EXPORT +FOR +FROM +IF +IMPLEMENTATION +IMPORT +IN +LOOP +MOD +MODULE +NOT +OF +OR +POINTER +PROCEDURE +QUALIFIED +RECORD +REPEAT +RETURN +SET +THEN +TO +TYPE +UNTIL +VAR +WHILE +WITH diff --git a/tests/modula3.gperf b/tests/modula3.gperf new file mode 100644 index 0000000..d024346 --- /dev/null +++ b/tests/modula3.gperf @@ -0,0 +1,106 @@ +AND +ARRAY +BEGIN +BITS +BY +CASE +CONST +DIV +DO +ELSE +ELSIF +END +EVAL +EXCEPT +EXCEPTION +EXIT +EXPORTS +FINALLY +FOR +FROM +IF +IMPORT +INTERFACE +IN +INLINE +LOCK +METHODS +MOD +MODULE +NOT +OBJECT +OF +OR +PROCEDURE +RAISES +READONLY +RECORD +REF +REPEAT +RETURN +SET +THEN +TO +TRY +TYPE +TYPECASE +UNSAFE +UNTIL +UNTRACED +VALUE +VAR +WHILE +WITH +and +array +begin +bits +by +case +const +div +do +else +elsif +end +eval +except +exception +exit +exports +finally +for +from +if +import +interface +in +inline +lock +methods +mod +module +not +object +of +or +procedure +raises +readonly +record +ref +repeat +return +set +then +to +try +type +typecase +unsafe +until +untraced +value +var +while +with diff --git a/tests/pascal.exp b/tests/pascal.exp new file mode 100644 index 0000000..765e44c --- /dev/null +++ b/tests/pascal.exp @@ -0,0 +1,36 @@ +in word set with +in word set array +in word set and +in word set function +in word set case +in word set var +in word set const +in word set until +in word set then +in word set set +in word set record +in word set program +in word set procedure +in word set or +in word set packed +in word set not +in word set nil +in word set label +in word set in +in word set repeat +in word set of +in word set goto +in word set forward +in word set for +in word set while +in word set file +in word set else +in word set downto +in word set do +in word set div +in word set to +in word set type +in word set end +in word set mod +in word set begin +in word set if diff --git a/tests/pascal.gperf b/tests/pascal.gperf new file mode 100644 index 0000000..fed3fbb --- /dev/null +++ b/tests/pascal.gperf @@ -0,0 +1,36 @@ +with +array +and +function +case +var +const +until +then +set +record +program +procedure +or +packed +not +nil +label +in +repeat +of +goto +forward +for +while +file +else +downto +do +div +to +type +end +mod +begin +if diff --git a/tests/test-1.exp b/tests/test-1.exp new file mode 100644 index 0000000..462fea5 --- /dev/null +++ b/tests/test-1.exp @@ -0,0 +1,153 @@ +/* C code produced by gperf version 2.7 */ +/* Command-line: ../src/gperf -p -j1 -g -o -t -N is_reserved_word -k1,3,$ */ +/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ +struct resword { char *name; short token; enum rid rid; }; + +#define TOTAL_KEYWORDS 51 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 13 +#define MIN_HASH_VALUE 8 +#define MAX_HASH_VALUE 82 +/* maximum key range = 75, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#endif +static unsigned int +hash (str, len) + register const char *str; + register unsigned int len; +{ + static unsigned char asso_values[] = + { + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 0, 83, 1, 2, 34, + 19, 6, 11, 29, 0, 17, 83, 0, 23, 28, + 26, 30, 31, 83, 15, 1, 0, 28, 13, 4, + 83, 83, 5, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83 + }; + register int hval = len; + + switch (hval) + { + default: + case 3: + hval += asso_values[(unsigned char)str[2]]; + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#endif +struct resword * +is_reserved_word (str, len) + register const char *str; + register unsigned int len; +{ + static struct resword wordlist[] = + { + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {"__asm__", ASM, NORID}, + {""}, + {"__typeof__", TYPEOF, NORID}, + {"__signed__", TYPESPEC, RID_SIGNED}, + {"__alignof__", ALIGNOF, NORID}, + {"break", BREAK, NORID}, + {"__attribute__", ATTRIBUTE, NORID}, + {""}, {""}, + {"else", ELSE, NORID}, + {"__attribute", ATTRIBUTE, NORID}, + {"__typeof", TYPEOF, NORID}, + {"int", TYPESPEC, RID_INT}, + {"__alignof", ALIGNOF, NORID}, + {"struct", STRUCT, NORID}, + {"sizeof", SIZEOF, NORID}, + {"switch", SWITCH, NORID}, + {"__volatile__", TYPE_QUAL, RID_VOLATILE}, + {""}, + {"__inline__", SCSPEC, RID_INLINE}, + {"__signed", TYPESPEC, RID_SIGNED}, + {"__volatile", TYPE_QUAL, RID_VOLATILE}, + {"if", IF, NORID}, + {"__inline", SCSPEC, RID_INLINE}, + {"while", WHILE, NORID}, + {""}, + {"__asm", ASM, NORID}, + {"auto", SCSPEC, RID_AUTO}, + {"short", TYPESPEC, RID_SHORT}, + {"default", DEFAULT, NORID}, + {"extern", SCSPEC, RID_EXTERN}, + {""}, {""}, + {"__const", TYPE_QUAL, RID_CONST}, + {"static", SCSPEC, RID_STATIC}, + {"__const__", TYPE_QUAL, RID_CONST}, + {"for", FOR, NORID}, + {"case", CASE, NORID}, + {"float", TYPESPEC, RID_FLOAT}, + {"return", RETURN, NORID}, + {"typeof", TYPEOF, NORID}, + {"typedef", SCSPEC, RID_TYPEDEF}, + {"volatile", TYPE_QUAL, RID_VOLATILE}, + {"do", DO, NORID}, + {"inline", SCSPEC, RID_INLINE}, + {"void", TYPESPEC, RID_VOID}, + {"char", TYPESPEC, RID_CHAR}, + {"signed", TYPESPEC, RID_SIGNED}, + {"unsigned", TYPESPEC, RID_UNSIGNED}, + {""}, {""}, + {"double", TYPESPEC, RID_DOUBLE}, + {"asm", ASM, NORID}, + {""}, {""}, + {"goto", GOTO, NORID}, + {""}, + {"const", TYPE_QUAL, RID_CONST}, + {"enum", ENUM, NORID}, + {"register", SCSPEC, RID_REGISTER}, + {""}, {""}, {""}, {""}, {""}, {""}, + {"continue", CONTINUE, NORID}, + {""}, + {"union", UNION, NORID}, + {""}, {""}, {""}, {""}, {""}, + {"long", TYPESPEC, RID_LONG} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register const char *s = wordlist[key].name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[key]; + } + } + return 0; +} diff --git a/tests/test-2.exp b/tests/test-2.exp new file mode 100644 index 0000000..3b9e7b0 --- /dev/null +++ b/tests/test-2.exp @@ -0,0 +1,202 @@ +/* C code produced by gperf version 2.7 */ +/* Command-line: ../src/gperf -n -k1-8 -l */ + +#define TOTAL_KEYWORDS 40 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 14 +#define MIN_HASH_VALUE 1 +#define MAX_HASH_VALUE 256 +/* maximum key range = 256, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#endif +static unsigned int +hash (str, len) + register const char *str; + register unsigned int len; +{ + static unsigned short asso_values[] = + { + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 25, 30, 35, 21, 0, + 30, 15, 30, 45, 257, 257, 0, 5, 45, 0, + 10, 0, 1, 20, 25, 15, 30, 40, 15, 5, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 257 + }; + register int hval = 0; + + switch (len) + { + default: + case 8: + hval += asso_values[(unsigned char)str[7]]; + case 7: + hval += asso_values[(unsigned char)str[6]]; + case 6: + hval += asso_values[(unsigned char)str[5]]; + case 5: + hval += asso_values[(unsigned char)str[4]]; + case 4: + hval += asso_values[(unsigned char)str[3]]; + case 3: + hval += asso_values[(unsigned char)str[2]]; + case 2: + hval += asso_values[(unsigned char)str[1]]; + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval; +} + +#ifdef __GNUC__ +__inline +#endif +const char * +in_word_set (str, len) + register const char *str; + register unsigned int len; +{ + static unsigned char lengthtable[] = + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 0, 2, 3, 0, + 0, 0, 2, 3, 0, 0, 0, 2, 4, 0, 0, 0, 4, 6, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 3, 5, 6, 0, 0, 6, 0, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 9, + 0, 4, 6, 6, 0, 0, 2, 3, 0, 0, 0, 5, 3, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 7, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10 + }; + static const char * wordlist[] = + { + "", + "OR", + "", "", "", "", "", "", "", "", + "LOOP", + "", "", "", "", "", "", "", "", "", + "ELSE", + "DO", + "", "", "", + "TO", + "MOD", + "", "", "", + "OF", + "FOR", + "", "", "", + "BY", + "FROM", + "", "", "", + "TYPE", + "MODULE", + "", "", "", + "SET", + "", "", "", "", "", + "EXPORT", + "", "", "", "", + "VAR", + "ARRAY", + "RECORD", + "", "", + "REPEAT", + "", "", "", "", + "END", + "", "", "", + "NOT", + "", "", "", "", + "IF", + "", "", "", "", + "CASE", + "", "", + "PROCEDURE", + "", + "EXIT", + "IMPORT", + "RETURN", + "", "", + "IN", + "AND", + "", "", "", + "ELSIF", + "DIV", + "", "", "", + "THEN", + "", "", "", "", "", "", "", "", "", + "IMPLEMENTATION", + "", "", "", "", + "WHILE", + "", "", "", "", "", "", "", "", "", + "CONST", + "POINTER", + "", "", "", + "UNTIL", + "", "", "", "", + "BEGIN", + "", "", "", "", + "WITH", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", + "QUALIFIED", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", + "", "", "", "", "", + "DEFINITION" + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + if (len == lengthtable[key]) + { + register const char *s = wordlist[key]; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return s; + } + } + return 0; +} diff --git a/tests/test-3.exp b/tests/test-3.exp new file mode 100644 index 0000000..fe0a1a6 --- /dev/null +++ b/tests/test-3.exp @@ -0,0 +1,186 @@ +/* C code produced by gperf version 2.7 */ +/* Command-line: ../src/gperf -p -j 1 -o -a -C -g -t -k1,4,$ */ +/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ gplus.gperf */ +struct resword { char *name; short token; enum rid rid;}; + +#define TOTAL_KEYWORDS 71 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 13 +#define MIN_HASH_VALUE 4 +#define MAX_HASH_VALUE 147 +/* maximum key range = 144, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#endif +static unsigned int +hash (str, len) + register const char *str; + register unsigned int len; +{ + static const unsigned char asso_values[] = + { + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 0, 148, 19, 6, 27, + 37, 0, 12, 1, 15, 63, 148, 4, 0, 56, + 20, 15, 42, 148, 31, 5, 26, 39, 32, 10, + 148, 40, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148 + }; + register int hval = len; + + switch (hval) + { + default: + case 4: + hval += asso_values[(unsigned char)str[3]]; + case 3: + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#endif +const struct resword * +in_word_set (str, len) + register const char *str; + register unsigned int len; +{ + static const struct resword wordlist[] = + { + {""}, {""}, {""}, {""}, + {"else", ELSE, NORID,}, + {""}, + {"long", TYPESPEC, RID_LONG,}, + {""}, {""}, {""}, {""}, + {"__alignof__", ALIGNOF, NORID}, + {"__asm__", ASM, NORID}, + {""}, {""}, + {"while", WHILE, NORID,}, + {""}, {""}, {""}, {""}, {""}, + {"__alignof", ALIGNOF, NORID}, + {"all", ALL, NORID /* Extension */,}, + {"sizeof", SIZEOF, NORID,}, + {"__const__", TYPE_QUAL, RID_CONST}, + {"__volatile", TYPE_QUAL, RID_VOLATILE}, + {"extern", SCSPEC, RID_EXTERN,}, + {"__volatile__", TYPE_QUAL, RID_VOLATILE}, + {"__inline", SCSPEC, RID_INLINE}, + {"exception", AGGR, RID_EXCEPTION /* Extension */,}, + {"__inline__", SCSPEC, RID_INLINE}, + {"case", CASE, NORID,}, + {"except", EXCEPT, NORID /* Extension */,}, + {"new", NEW, NORID,}, + {"break", BREAK, NORID,}, + {"goto", GOTO, NORID,}, + {""}, + {"__attribute", ATTRIBUTE, NORID}, + {""}, + {"__attribute__", ATTRIBUTE, NORID}, + {"this", THIS, NORID,}, + {"raise", RAISE, NORID /* Extension */,}, + {"class", AGGR, RID_CLASS,}, + {"delete", DELETE, NORID,}, + {"typeof", TYPEOF, NORID,}, + {"typedef", SCSPEC, RID_TYPEDEF,}, + {"for", FOR, NORID,}, + {"raises", RAISES, NORID /* Extension */,}, + {"__const", TYPE_QUAL, RID_CONST}, + {"double", TYPESPEC, RID_DOUBLE,}, + {"__typeof__", TYPEOF, NORID}, + {""}, + {"switch", SWITCH, NORID,}, + {"auto", SCSPEC, RID_AUTO,}, + {"do", DO, NORID,}, + {"friend", SCSPEC, RID_FRIEND,}, + {""}, + {"reraise", RERAISE, NORID /* Extension */,}, + {""}, + {"volatile", TYPE_QUAL, RID_VOLATILE,}, + {"__typeof", TYPEOF, NORID}, + {"continue", CONTINUE, NORID,}, + {"float", TYPESPEC, RID_FLOAT,}, + {"const", TYPE_QUAL, RID_CONST,}, + {"static", SCSPEC, RID_STATIC,}, + {"virtual", SCSPEC, RID_VIRTUAL,}, + {"__asm", ASM, NORID}, + {"short", TYPESPEC, RID_SHORT,}, + {"signed", TYPESPEC, RID_SIGNED,}, + {"try", TRY, NORID /* Extension */,}, + {""}, {""}, {""}, + {"__signed__", TYPESPEC, RID_SIGNED}, + {"catch", CATCH, NORID,}, + {"public", PUBLIC, NORID,}, + {"struct", AGGR, RID_RECORD,}, + {"if", IF, NORID,}, + {"asm", ASM, NORID,}, + {"union", AGGR, RID_UNION,}, + {""}, + {"private", PRIVATE, NORID,}, + {""}, {""}, {""}, + {"operator", OPERATOR, NORID,}, + {""}, {""}, {""}, + {"default", DEFAULT, NORID,}, + {"dynamic", DYNAMIC, NORID,}, + {"overload", OVERLOAD, NORID,}, + {"int", TYPESPEC, RID_INT,}, + {"char", TYPESPEC, RID_CHAR,}, + {""}, {""}, + {"return", RETURN, NORID,}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, + {"__signed", TYPESPEC, RID_SIGNED}, + {""}, + {"void", TYPESPEC, RID_VOID,}, + {""}, {""}, {""}, + {"protected", PROTECTED, NORID,}, + {""}, + {"enum", ENUM, NORID,}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, + {"inline", SCSPEC, RID_INLINE,}, + {"register", SCSPEC, RID_REGISTER,}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, + {"unsigned", TYPESPEC, RID_UNSIGNED,} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register const char *s = wordlist[key].name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[key]; + } + } + return 0; +} diff --git a/tests/test-4.exp b/tests/test-4.exp new file mode 100644 index 0000000..b527968 --- /dev/null +++ b/tests/test-4.exp @@ -0,0 +1,162 @@ +/* C code produced by gperf version 2.7 */ +/* Command-line: ../src/gperf -D -p -t */ +/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ +struct resword { char *name; short token; enum rid rid; }; + +#define TOTAL_KEYWORDS 51 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 13 +#define MIN_HASH_VALUE 4 +#define MAX_HASH_VALUE 82 +/* maximum key range = 79, duplicates = 2 */ + +#ifdef __GNUC__ +__inline +#endif +static unsigned int +hash (str, len) + register const char *str; + register unsigned int len; +{ + static unsigned char asso_values[] = + { + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 0, 83, 40, 20, 50, + 25, 10, 30, 0, 0, 50, 83, 0, 15, 0, + 35, 0, 83, 83, 20, 0, 10, 40, 5, 15, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83 + }; + return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; +} + +#ifdef __GNUC__ +__inline +#endif +struct resword * +in_word_set (str, len) + register const char *str; + register unsigned int len; +{ + static struct resword wordlist[] = + { + {"goto", GOTO, NORID}, + {"__asm", ASM, NORID}, + {"switch", SWITCH, NORID}, + {"__asm__", ASM, NORID}, + {"__const__", TYPE_QUAL, RID_CONST}, + {"__inline__", SCSPEC, RID_INLINE}, + {"__typeof__", TYPEOF, NORID}, + {"__signed__", TYPESPEC, RID_SIGNED}, + {"__alignof__", ALIGNOF, NORID}, + {"__volatile__", TYPE_QUAL, RID_VOLATILE}, + {"__attribute__", ATTRIBUTE, NORID}, + {"enum", ENUM, NORID}, + {"short", TYPESPEC, RID_SHORT}, + {"struct", STRUCT, NORID}, + {"__const", TYPE_QUAL, RID_CONST}, + {"__inline", SCSPEC, RID_INLINE}, + {"long", TYPESPEC, RID_LONG}, + {"__volatile", TYPE_QUAL, RID_VOLATILE}, + {"__attribute", ATTRIBUTE, NORID}, + {"volatile", TYPE_QUAL, RID_VOLATILE}, + {"else", ELSE, NORID}, + {"break", BREAK, NORID}, + {"do", DO, NORID}, + {"while", WHILE, NORID}, + {"signed", TYPESPEC, RID_SIGNED}, + {"__signed", TYPESPEC, RID_SIGNED}, + {"void", TYPESPEC, RID_VOID}, + {"sizeof", SIZEOF, NORID}, + {"__typeof", TYPEOF, NORID}, + {"__alignof", ALIGNOF, NORID}, + {"double", TYPESPEC, RID_DOUBLE}, + {"default", DEFAULT, NORID}, + {"asm", ASM, NORID}, + {"auto", SCSPEC, RID_AUTO}, + {"float", TYPESPEC, RID_FLOAT}, + {"typeof", TYPEOF, NORID}, + {"typedef", SCSPEC, RID_TYPEDEF}, + {"register", SCSPEC, RID_REGISTER}, + {"extern", SCSPEC, RID_EXTERN}, + {"for", FOR, NORID}, + {"static", SCSPEC, RID_STATIC}, + {"return", RETURN, NORID}, + {"int", TYPESPEC, RID_INT}, + {"case", CASE, NORID}, + {"const", TYPE_QUAL, RID_CONST}, + {"inline", SCSPEC, RID_INLINE}, + {"continue", CONTINUE, NORID}, + {"unsigned", TYPESPEC, RID_UNSIGNED}, + {"char", TYPESPEC, RID_CHAR}, + {"union", UNION, NORID}, + {"if", IF, NORID} + }; + + static short lookup[] = + { + -1, -1, -1, -1, 0, 1, 2, 3, -1, 4, + -80, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, -1, 19, 20, 21, -1, 22, -46, -3, + 23, 24, -1, 25, 26, -1, 27, -1, 28, 29, + -1, 30, 31, 32, 33, 34, 35, 36, 37, -1, + -1, 38, -1, 39, -1, -1, 40, -1, -1, -1, + -1, 41, -1, 42, 43, 44, 45, -1, 46, -1, + -1, -1, -1, 47, 48, -1, -1, -1, -1, -1, + 49, -1, 50 + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int index = lookup[key]; + + if (index >= 0) + { + register const char *s = wordlist[index].name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[index]; + } + else if (index < -TOTAL_KEYWORDS) + { + register int offset = - 1 - TOTAL_KEYWORDS - index; + register struct resword *wordptr = &wordlist[TOTAL_KEYWORDS + lookup[offset]]; + register struct resword *wordendptr = wordptr + -lookup[offset + 1]; + + while (wordptr < wordendptr) + { + register const char *s = wordptr->name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return wordptr; + wordptr++; + } + } + } + } + return 0; +} diff --git a/tests/test-5.exp b/tests/test-5.exp new file mode 100644 index 0000000..8f4d9ab --- /dev/null +++ b/tests/test-5.exp @@ -0,0 +1,124 @@ +/* C code produced by gperf version 2.7 */ +/* Command-line: ../src/gperf -g -o -j1 -t -p -N is_reserved_word */ +/* ISO Pascal 7185 reserved words. + * + * For GNU Pascal compiler (GPC) by jtv@hut.fi + * + * run this through the Doug Schmidt's gperf program + * with command + * gperf -g -o -j1 -t -p -N is_reserved_word + * + */ +struct resword { char *name; short token; short iclass;}; + +#define TOTAL_KEYWORDS 35 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 9 +#define MIN_HASH_VALUE 2 +#define MAX_HASH_VALUE 43 +/* maximum key range = 42, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#endif +static unsigned int +hash (str, len) + register const char *str; + register unsigned int len; +{ + static unsigned char asso_values[] = + { + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 18, 29, 14, 6, 7, + 10, 20, 44, 28, 44, 44, 28, 19, 22, 15, + 0, 44, 9, 23, 0, 23, 26, 2, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 0, 0, 13, 44, 30, 44, 44, 44, 0, 25, + 1, 0, 44, 44, 0, 44, 1, 44, 25, 44, + 44, 0, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44 + }; + return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; +} + +#ifdef __GNUC__ +__inline +#endif +struct resword * +is_reserved_word (str, len) + register const char *str; + register unsigned int len; +{ + static struct resword wordlist[] = + { + {""}, {""}, + {"To", TO, PASCAL_ISO}, + {""}, + {"Type", TYPE, PASCAL_ISO}, + {"Then", THEN, PASCAL_ISO}, + {"Packed", PACKED, PASCAL_ISO}, + {"While", WHILE, PASCAL_ISO}, + {"Do", DO, PASCAL_ISO}, + {"Procedure", PROCEDURE, PASCAL_ISO}, + {"End", END, PASCAL_ISO}, + {"Else", ELSE, PASCAL_ISO}, + {"Downto", DOWNTO, PASCAL_ISO}, + {"For", FOR, PASCAL_ISO}, + {"File", FILE_, PASCAL_ISO}, + {"Record", RECORD, PASCAL_ISO}, + {"Repeat", REPEAT, PASCAL_ISO}, + {"Or", OR, PASCAL_ISO}, + {"Case", CASE, PASCAL_ISO}, + {"Function", FUNCTION, PASCAL_ISO}, + {"Const", CONST, PASCAL_ISO}, + {"And", AND, PASCAL_ISO}, + {"Mod", MOD, PASCAL_ISO}, + {"Array", ARRAY, PASCAL_ISO}, + {"Goto", GOTO, PASCAL_ISO}, + {"Nil", NIL, PASCAL_ISO}, + {"Not", NOT, PASCAL_ISO}, + {"Set", SET, PASCAL_ISO}, + {"Until", UNTIL, PASCAL_ISO}, + {"Var", VAR, PASCAL_ISO}, + {"Of", OF, PASCAL_ISO}, + {"In", IN, PASCAL_ISO}, + {"Program",PROGRAM,PASCAL_ISO}, + {"Label", LABEL, PASCAL_ISO}, + {"Div", DIV, PASCAL_ISO}, + {"Begin", BEGIN_, PASCAL_ISO}, + {"With", WITH, PASCAL_ISO}, + {""}, {""}, {""}, {""}, {""}, {""}, + {"If", IF, PASCAL_ISO} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register const char *s = wordlist[key].name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[key]; + } + } + return 0; +} diff --git a/tests/test-6.exp b/tests/test-6.exp new file mode 100644 index 0000000..3521f13 --- /dev/null +++ b/tests/test-6.exp @@ -0,0 +1,119 @@ +GNU `gperf' generates perfect hash functions. + +Usage: ../src/gperf [OPTION]... [INPUT-FILE] + +If a long option shows an argument as mandatory, then it is mandatory +for the equivalent short option also. + +Input file interpretation: + -e, --delimiters=DELIMITER-LIST + Allow user to provide a string containing delimiters + used to separate keywords from their attributes. + Default is ",\n". + -t, --struct-type 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. + +Language for the output code: + -L, --language=LANGUAGE-NAME + Generates code in the specified language. Languages + handled are currently C++, ANSI-C, C, and KR-C. The + default is C. + +Details in the output code: + -K, --slot-name=NAME Select name of the keyword component in the keyword + structure. + -H, --hash-fn-name=NAME + Specify name of generated hash function. Default is + `hash'. + -N, --lookup-fn-name=NAME + Specify name of generated lookup function. Default + name is `in_word_set'. + -Z, --class-name=NAME Specify name of generated C++ class. Default name is + `Perfect_Hash'. + -7, --seven-bit Assume 7-bit characters. + -c, --compare-strncmp Generate comparison code using strncmp rather than + strcmp. + -C, --readonly-tables Make the contents of generated lookup tables + constant, i.e., readonly. + -E, --enum Define constant values using an enum local to the + lookup function rather than with defines. + -I, --includes Include the necessary system include file + at the beginning of the code. + -G, --global 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). + -W, --word-array-name=NAME + Specify name of word list array. Default name is + `wordlist'. + -S, --switch=COUNT 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. + -T, --omit-struct-type + Prevents the transfer of the type declaration to the + output file. Use this option if the type is already + defined elsewhere. + +Algorithm employed by gperf: + -k, --key-positions=KEYS + Select the key positions used in the hash function. + The allowable choices range between 1-126, 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. + -l, --compare-strlen Compare key lengths before trying a string + comparison. This helps cut down on the number of + string comparisons made during the lookup. + -D, --duplicates Handle keywords that hash to duplicate values. This + is useful for certain highly redundant keyword sets. + -f, --fast=ITERATIONS Generate the gen-perf.hash function ``fast''. This + decreases gperf's running time at the cost of + minimizing generated table size. The numeric + argument represents the number of times to iterate + when resolving a collision. `0' means ``iterate by + the number of keywords''. + -i, --initial-asso=N Provide an initial value for the associate values + array. Default is 0. Setting this value larger helps + inflate the size of the final table. + -j, --jump=JUMP-VALUE Affects the ``jump value'', i.e., how far to advance + the associated character value upon collisions. Must + be an odd number, default is 5. + -n, --no-strlen Do not include the length of the keyword when + computing the hash function. + -o, --occurrence-sort Reorders input keys by frequency of occurrence of + the key sets. This should decrease the search time + dramatically. + -r, --random Utilizes randomness to initialize the associated + values table. + -s, --size-multiple=N 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 -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. + +Informative output: + -h, --help Print this message. + -v, --version Print the gperf version number. + -d, --debug Enables the debugging option (produces verbose + output to the standard error). + +Report bugs to . diff --git a/tests/test-7.exp b/tests/test-7.exp new file mode 100644 index 0000000..c5c942c --- /dev/null +++ b/tests/test-7.exp @@ -0,0 +1,32 @@ +in word set if +in word set do +NOT in word set int +in word set for +in word set case +NOT in word set char +NOT in word set auto +in word set goto +in word set else +NOT in word set long +NOT in word set void +NOT in word set enum +NOT in word set float +NOT in word set short +NOT in word set union +NOT in word set break +in word set while +NOT in word set const +NOT in word set double +NOT in word set static +NOT in word set extern +NOT in word set struct +in word set return +NOT in word set sizeof +NOT in word set switch +NOT in word set signed +NOT in word set typedef +NOT in word set default +NOT in word set unsigned +NOT in word set continue +NOT in word set register +NOT in word set volatile diff --git a/tests/test.c b/tests/test.c new file mode 100644 index 0000000..5d78156 --- /dev/null +++ b/tests/test.c @@ -0,0 +1,26 @@ +/* + Tests the generated perfect hash function. + The -v option prints diagnostics as to whether a word is in + the set or not. Without -v the program is useful for timing. +*/ + +#include + +#define MAX_LEN 80 + +int +main (argc, argv) + int argc; + char *argv[]; +{ + int verbose = argc > 1 ? 1 : 0; + char buf[MAX_LEN]; + + while (gets (buf)) + if (in_word_set (buf, strlen (buf)) && verbose) + printf ("in word set %s\n", buf); + else if (verbose) + printf ("NOT in word set %s\n", buf); + + return 0; +} diff --git a/tests/validate b/tests/validate new file mode 100755 index 0000000..a4813ab --- /dev/null +++ b/tests/validate @@ -0,0 +1,54 @@ +#! /bin/sh +# Validate gperf's operation on a given input file. +# Usage: validate languages input.gperf [more gperf options] +# Uses the environment variables GPERF, CC, CFLAGS, CXX, CXXFLAGS. +# Supposes gcc and g++. + +# Exit on error +set -e + +verbose () { + echo "$@" + "$@" +} + +languages=$1 +shift + +for lang in `echo $languages | sed -e 's/,/ /g'`; do + case "$lang" in + KR-C ) + echo "${GPERF} -I -L KR-C $@ > valitest.c" + ${GPERF} -I -L KR-C "$@" > valitest.c + grep -n ' const ' valitest.c /dev/null && exit 1 + verbose ${CC} ${CFLAGS} -traditional valitest.c -o valitest + ./valitest + verbose ${CC} ${CFLAGS} -ansi -pedantic valitest.c -o valitest + ./valitest + ;; + C ) + echo "${GPERF} -I -L C $@ > valitest.c" + ${GPERF} -I -L C "$@" > valitest.c + verbose ${CC} ${CFLAGS} -traditional -Dconst= valitest.c -o valitest + ./valitest + verbose ${CC} ${CFLAGS} -ansi -pedantic -pedantic-errors valitest.c -o valitest + ./valitest + ;; + ANSI-C ) + echo "${GPERF} -I -L ANSI-C $@ > valitest.c" + ${GPERF} -I -L ANSI-C "$@" > valitest.c + verbose ${CC} ${CFLAGS} -ansi -pedantic -pedantic-errors valitest.c -o valitest + ./valitest + verbose ${CXX} ${CXXFLAGS} -ansi -pedantic -pedantic-errors valitest.c -o valitest + ./valitest + ;; + "C++" ) + echo "${GPERF} -I -L C++ $@ > valitest.c" + ${GPERF} -I -L C++ "$@" > valitest.c + verbose ${CXX} ${CXXFLAGS} -ansi -pedantic -pedantic-errors -DCPLUSPLUS_TEST valitest.c -o valitest + ./valitest + ;; + esac +done + +exit 0