commit 501ee3e64033e900181aaebd7ae44dbcacccca9d Author: Bruno Haible Date: Sat Aug 19 06:20:11 2000 +0000 Initial revision 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 0000000..cc1f020 Binary files /dev/null and b/doc/gperf.dvi differ diff --git a/doc/gperf.html b/doc/gperf.html new file mode 100644 index 0000000..9781687 --- /dev/null +++ b/doc/gperf.html @@ -0,0 +1,1381 @@ + + + + +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