Import the FSF release of gperf-2.1a, used in the build of gcc-2.7.2.1

(to be imported soon).
This commit is contained in:
Peter Wemm 1996-09-10 13:48:14 +00:00
commit dcd8284393
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/gperf/dist/; revision=18214
svn path=/vendor/gperf/2.1a/; revision=18216; tag=vendor/gperf/2.1a
44 changed files with 6163 additions and 0 deletions

249
contrib/gperf/COPYING Normal file
View File

@ -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.
<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., 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.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

375
contrib/gperf/ChangeLog Normal file
View File

@ -0,0 +1,375 @@
Sat Nov 11 13:43:17 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Modified options by changing macro TOTAL_POSITIONS to GET_CHARSET_SIZE
and 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.
Fri Nov 10 15:21:19 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Made sure to explicitly initialize perfect.fewest_collisions to
0.
Wed Nov 1 21:39:54 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Upgraded the version number to 2.0, reflecting all the
major recent changes!
* Rearranged code so that fewer source lines are greater than 80 columns.
* Cleaned up some loose ends noticed by Nels Olson.
1. Removed `if (collisions <= perfect.fewest_collisions)'
from affects_prev () since it was superfluous.
2. Removed the fields best_char_value and best_asso_value
from PERFECT. There were also unnecessary.
3. Fixed a braino in boolarray.c's 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. Broke the -h help options string into 3 pieces. This
should silence broken C compilers for a while!
5. Modified `report_error ()' so that it correctly handled
"%%".
Tue Oct 31 23:01:11 1989 Doug Schmidt (schmidt at siam.ics.uci.edu)
* 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 print_switch so that if finally
seems to work correctly. Needs more stress testing, however...
Mon Oct 30 15:06:59 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Made a major change to the keylist.c's 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 keylist.c's length () function to keyword_list_length ().
Also put an extern decl for this function and max_key_length ()
into the keylist.h file (don't know why it wasn't already there...).
Sun Oct 29 08:55:29 1989 Doug Schmidt (schmidt at siam.ics.uci.edu)
* 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 hashtable.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.
* Modified xmalloc.c's buffered_malloc () routine so that it
rounded the SIZE byte requests up to the correct alignment
size for the target machine.
Sat Oct 28 11:17:36 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu)
* Fixed a stupid bug in keylist.c's 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 LIST_NODE so that the char *char_set field is redeclared
as char char_set[1] and placed at the bottom of the struct. This
enables us to play the old `variable-length string in the struct
trick' (third time I fell for it this week, chief!). The
main purpose of this is to remove n calls to buffered_malloc,
where n is the number of keywords.
* Added a new function to xmalloc.c called buffered_malloc. This
reduces the number of calls to malloc by grabbing large chunks
of memory and doling them out in small pieces. Almost all uses
of xmalloc were replaced with calls to buffered_malloc ().
* Modified boolarray.c's bool_array_destroy () function 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 hash_table_init. This function is
now passed a pointer to a power-of-two sized buffer that serves
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 keylist.c's read_keys () calling
interface.
* Since alloca is now being used more aggressively a conditional
compilation section was added to the init_all () routine 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.
* Moved the `destructor' for bool_array from destroy_all () in
main.c into perfect_generate () in perfect.c. This enables
us to get free up the large dynamic memory as soon as it is no
longer necessary. Also moved the hash_table destructor from
destroy_all into read_keys () from keylist.c. This accomplishes
the same purpose, i.e., we can free up the space immediately.
* Added warnings in option.c so that user's would be informed
that -r superceeds -i on the command-line.
* Rewrote affects_prev () from perfect.c. First, the code structure
was cleaned up considerably (removing the need for a dreaded
goto!). Secondly, a major change occurred so that 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 change () routine from perfect.c
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 xmalloc in perfect.c's change () function.
This should eliminate some overhead at the expense of a little
extra memory that is never reclaimed.
* Renamed perfect.c's merge_sets () to compute_disjoint_union ()
to reflect the change in behavior.
Fri Oct 27 10:12:27 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu)
* 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 perfect.c's merge_set () described below 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 the print_switch () from keylist.c.
A right paren was placed at the wrong location.
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. Finally split the huge help string into two parts. This keeps
breaking compilers with static limits on the length of tokens...
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 PERFECT 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 perfect.c function affect_prev () doesn't
waste time trying to change an associated value that is
shared between two conflicting keywords.
9. Modified affects_prev so that it doesn't try random jump
values unless the -j 0 option is enabled.
10. Fixed a silly bug in perfect.c change ().
This problem caused gperf to seg fault when
the -k* option was given and the keyfile file had long
keywords.
11. Changed the behavior of keylist.c's read_keys () routine
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.
Mon Oct 16 19:58:08 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu)
* Fixed a number of small bugs kindly brought to my attention by
Adam de Boor (bsw!adam@uunet.UU.NET). Thanks Adam! In particular,
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 <stddef.h> all
over the place...
* 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 allocate 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!
Thu Oct 12 18:08:43 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Updated the version number to 1.9.
* 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;
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).
Mon Jul 24 17:09:46 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu)
* Fixed a bug in PRINT_MIN_MAX that resulted in MAX_INT being printed
for the MIN_KEY_LEN if there was only 1 keyword in the input file
(yeah, that's a pretty unlikely occurrence, I agree!).
* 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 horrible typo in PRINT_KEYWORD_TABLE in keylist.cc
that prevented links from being printed correctly.
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 12:14:04 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu)
* Moved comment handling from keylist.c to readline.c. This
simplifies the code and reduces the number of malloc calls.
* 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.
Sat Jul 1 10:12:21 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu)
* Added the "#" feature, that allows comments inside the keyword
list from the input file.
* 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).
Fri Jun 30 18:22:35 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu)
* Added Adam de Boor's changes. Created an UNSET_OPTION macro.
Sat Jun 17 10:56:00 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu)
* Modified option.h and option.c so that all mixed operations
between integers and enumerals are cast correctly to int.
This prevents errors in some brain-damaged C compilers.
Fri Jun 16 14:13:15 1989 Doug Schmidt (schmidt at crimee.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.
Wed Jun 7 23:07:13 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Updated to version 1.8 in preparation to release to Doug Lea
and FSF.
* Added the -c (comparison) option. Enabling this
will use the strncmp function for string comparisons.
The default is to use strcmp.
Tue Jun 6 16:32:09 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Fixed another stupid typo in xmalloc.c (XMALLOC). I accidentally
left the ANSI-fied prototype in place. This obviously
fails on old-style C compilers.
* Fixed stupid typos in PRINT_SWITCH from the keylist.c. This
caused the -D option to produce incorrect output when used
in conjunction with -p and -t.
* Replaced the use of STRCMP with STRNCMP for the generated
C output code.
Fri Jun 2 23:16:01 1989 Doug Schmidt (schmidt at trinite.ics.uci.edu)
* Added a new function (XMALLOC) and file (xmalloc.c). All
calls to MALLOC were replaced by calls to XMALLOC. This
will complain when virtual memory runs out (don't laugh,
this has happened!)
Thu Jun 1 21:10:10 1989 Doug Schmidt (schmidt at zola.ics.uci.edu)
* Fixed a typo in options.c that prevented the -f option
from being given on the command-line.
Wed May 3 17:48:02 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.
* Fixed a typo in perfect.c perfect_destroy that prevented the actual
maximum hash table size from being printed.
* 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)
* Enabled the diagnostics dump if the debugging option is enabled.
* Removed all calls to FREE (silly to do this at program termination).
* Ported gperf to C. From now on both K&R C and GNU G++ versions
will be supported.

41
contrib/gperf/Makefile Normal file
View File

@ -0,0 +1,41 @@
# Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA.
GPERF = ../src/gperf
all: gperf tests
gperf:
(cd src; $(MAKE))
tests: gperf
(cd tests; $(MAKE) GPERF=$(GPERF))
distrib:
(cd ..; rm -f cperf.tar.Z; tar cvf cperf.tar cperf; compress cperf.tar; uuencode cperf.tar.Z < cperf.tar.Z > CSHAR)
clean:
(cd src; $(MAKE) clean)
(cd tests; $(MAKE) clean)
realclean:
(cd src; $(MAKE) realclean)
(cd tests; $(MAKE) clean)
-rm -f gperf.info* gperf.?? gperf.??s gperf.log gperf.toc \
gperf.*aux *inset.c *out gperf

28
contrib/gperf/README Normal file
View File

@ -0,0 +1,28 @@
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 texinfo.tex macros needed to run
gperf.texinfo through TeX are available in the GNU GCC release. If
you don't have access to these please email me and I'll send them to
you (about 75k).
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
schmidt@ics.uci.edu

View File

@ -0,0 +1,8 @@
Note: Just for clarification, this version of `gperf' is written in
portable K&R C. The `gperf' supplied in the top-level libg++ directory on
this distribution tape is written in C++. Either will generate output for
C or C++, so which one to compile is up to you.
--Noah Friedman, GNU tape distribution maintainer.
friedman@prep.ai.mit.edu
December 24, 1991

23
contrib/gperf/gperf.1 Normal file
View File

@ -0,0 +1,23 @@
.TH GPERF 1 "December 16, 1988
.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.texinfo\fP file for more information.
This file is distributed with \fIgperf\fP release.

1129
contrib/gperf/gperf.texinfo Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
# Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA.
CC = gcc
DFLAGS= -DLO_CAL -DGATHER_STATISTICS #-DRLIMIT_STACK
OFLAGS= -O -p -g -fstrength-reduce -fomit-frame-pointer -fdelayed-branch -finline-functions # gcc options
CFLAGS= $(DFLAGS) $(OFLAGS)
OBJS = options.o iterator.o main.o perfect.o keylist.o listnode.o xmalloc.o \
hashtable.o boolarray.o readline.o stderr.o version.o getopt.o
SOURCES = options.c iterator.c main.c perfect.c keylist.c listnode.c xmalloc.c \
hashtable.c boolarray.c readline.c stderr.c version.c getopt.c
all: gperf
gperf: $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
clean:
-rm -f *.o core *~ #*#
realclean: clean
-rm -f gperf
# dependencies
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
boolarray.o: boolarray.c /usr/include/stdio.h boolarray.h prototype.h options.h
boolarray.o: /usr/include/stdio.h prototype.h
getopt.o: getopt.c /usr/include/stdio.h
hashtable.o: hashtable.c /usr/include/stdio.h hashtable.h keylist.h
hashtable.o: /usr/include/stdio.h listnode.h prototype.h prototype.h options.h
hashtable.o: /usr/include/stdio.h prototype.h
iterator.o: iterator.c /usr/include/stdio.h /usr/include/ctype.h iterator.h
iterator.o: prototype.h
keylist.o: keylist.c /usr/include/assert.h /usr/include/stdio.h options.h
keylist.o: /usr/include/stdio.h prototype.h readline.h prototype.h keylist.h
keylist.o: /usr/include/stdio.h listnode.h prototype.h hashtable.h keylist.h
keylist.o: prototype.h stderr.h prototype.h /usr/include/varargs.h
listnode.o: listnode.c /usr/include/stdio.h options.h /usr/include/stdio.h
listnode.o: prototype.h listnode.h prototype.h stderr.h prototype.h
listnode.o: /usr/include/varargs.h
main.o: main.c /usr/include/stdio.h stderr.h prototype.h /usr/include/varargs.h
main.o: options.h /usr/include/stdio.h prototype.h perfect.h prototype.h
main.o: keylist.h /usr/include/stdio.h listnode.h prototype.h boolarray.h
main.o: prototype.h
options.o: options.c /usr/include/stdio.h /usr/include/assert.h options.h
options.o: /usr/include/stdio.h prototype.h iterator.h prototype.h stderr.h
options.o: prototype.h /usr/include/varargs.h
perfect.o: perfect.c /usr/include/stdio.h /usr/include/assert.h
perfect.o: /usr/include/ctype.h options.h /usr/include/stdio.h prototype.h
perfect.o: perfect.h prototype.h keylist.h /usr/include/stdio.h listnode.h
perfect.o: prototype.h boolarray.h prototype.h stderr.h prototype.h
perfect.o: /usr/include/varargs.h
readline.o: readline.c /usr/include/stdio.h readline.h prototype.h
stderr.o: stderr.c /usr/include/stdio.h stderr.h prototype.h
stderr.o: /usr/include/varargs.h
version.o: version.c
xmalloc.o: xmalloc.c /usr/include/stdio.h
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

View File

@ -0,0 +1,90 @@
/* Fast lookup table abstraction implemented as a Guilmette Array
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "boolarray.h"
#include "options.h"
/* Locally visible BOOL_ARRAY object. */
static BOOL_ARRAY bool_array;
/* Prints out debugging diagnostics. */
void
bool_array_destroy ()
{
if (OPTION_ENABLED (option, DEBUG))
fprintf (stderr, "\ndumping boolean array information\niteration number = %d\nend of array dump\n",
bool_array.iteration_number);
free ((char *) bool_array.storage_array);
}
void
bool_array_init (size)
int size;
{
STORAGE_TYPE *xmalloc ();
bool_array.iteration_number = 1;
bool_array.size = size;
bool_array.storage_array = xmalloc (size * sizeof *bool_array.storage_array);
bzero (bool_array.storage_array, size * sizeof *bool_array.storage_array);
if (OPTION_ENABLED (option, DEBUG))
fprintf (stderr, "\nbool array size = %d, total bytes = %d\n",
bool_array.size, bool_array.size * sizeof *bool_array.storage_array);
}
bool
lookup (index)
int index;
{
if (bool_array.storage_array[index] == bool_array.iteration_number)
return 1;
else
{
bool_array.storage_array[index] = bool_array.iteration_number;
return 0;
}
}
/* Simple enough to reset, eh?! */
void
bool_array_reset ()
{
/* If we wrap around it's time to zero things out again! */
if (++bool_array.iteration_number == 0)
{
if (OPTION_ENABLED (option, DEBUG))
{
fprintf (stderr, "(re-initializing bool_array)...");
fflush (stderr);
}
bool_array.iteration_number = 1;
bzero (bool_array.storage_array, bool_array.size * sizeof *bool_array.storage_array);
if (OPTION_ENABLED (option, DEBUG))
{
fprintf (stderr, "done\n");
fflush (stderr);
}
}
}

View File

@ -0,0 +1,48 @@
/* Simple lookup table abstraction implemented as a Guilmette Array.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define and implement a simple boolean array abstraction,
uses a Guilmette array implementation to save on initialization time. */
#ifndef _boolarray_h
#define _boolarray_h
#include "prototype.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 int STORAGE_TYPE;
#endif
typedef struct bool_array
{
STORAGE_TYPE *storage_array; /* Initialization of the index space. */
STORAGE_TYPE iteration_number; /* Keep track of the current iteration. */
int size; /* Size of the entire array (dynamically initialized). */
} BOOL_ARRAY;
extern void bool_array_init P ((int size));
extern void bool_array_destroy P ((void));
extern bool lookup P ((int hash_value));
extern void bool_array_reset P ((void));
#endif /* _boolarray_h */

413
contrib/gperf/src/getopt.c Normal file
View File

@ -0,0 +1,413 @@
/* Getopt for GNU.
Copyright (C) 1987, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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. */
/* 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 _POSIX_OPTION_ORDER 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 <stdio.h>
#ifdef sparc
#include <alloca.h>
#endif
#ifdef USG
#define bcopy(s, d, l) memcpy((d), (s), (l))
#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. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Describe how to deal with options that follow non-option ARGV-elements.
UNSPECIFIED means the caller did not specify anything;
the default is then REQUIRE_ORDER if the environment variable
_OPTIONS_FIRST 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.
PERMUTE is the default. We permute the contents of `argv' as we scan,
so that eventually all the 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 zero.
Using `-' as the first character of the list of option characters
requests this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int nonopts_size
= (last_nonopt - first_nonopt) * sizeof (char *);
char **temp = (char **) alloca (nonopts_size);
/* Interchange the two blocks of data in argv. */
bcopy (&argv[first_nonopt], temp, nonopts_size);
bcopy (&argv[last_nonopt], &argv[first_nonopt],
(optind - last_nonopt) * sizeof (char *));
bcopy (temp, &argv[first_nonopt + optind - last_nonopt],
nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* 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 theoption characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
A colon in OPTSTRING means that the previous character is an option
that wants an argument. The argument is taken from the rest of the
current ARGV-element, or from the following ARGV-element,
and returned in `optarg'.
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'.
If OPTSTRING starts with `-', it requests a different method of handling the
non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */
int
getopt (argc, argv, optstring)
int argc;
char **argv;
char *optstring;
{
/* Initialize the internal data when the first call is made.
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. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = 0;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
ordering = RETURN_IN_ORDER;
else if (getenv ("_POSIX_OPTION_ORDER") != 0)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == 0 || *nextchar == 0)
{
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 (argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-'
|| argv[optind][1] == 0))
optind++;
last_nonopt = optind;
}
/* 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 (argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if (argv[optind][0] != '-' || argv[optind][1] == 0)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 0;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = argv[optind] + 1;
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = (char *) index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == 0)
optind++;
if (temp == 0 || c == ':')
{
if (opterr != 0)
{
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n",
argv[0], c);
}
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != 0)
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = 0;
}
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 != 0)
fprintf (stderr, "%s: no argument for `-%c' option\n",
argv[0], c);
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = 0;
}
}
return c;
}
}
#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;
{
char c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind;
if ((c = getopt (argc, argv, "abc:d:0123456789")) == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
return 0;
}
#endif /* TEST */

View File

@ -0,0 +1,22 @@
1. provide output diagnostics that explain how many input keys total,
how many after dealing with static links, and finally, after the
algorithm is complete, how many dynamic duplicates do we now
have.
2. fix up GATHER_STATISTICS for all instrumentation.
3. Useful idea:
a. Generate the wordlist as a contiguous block of keywords, as before.
This wordlist *must* be sorted by hash value.
b. generate the lookup_array, which are an array of signed {chars,shorts,ints},
which ever allows full coverage of the wordlist dimensions. If the
value v, where v = lookup_array[hash(str,len)], is >= 0, then we
simply use this result as a direct access into wordlist to snag
the keyword for comparison.
c. Otherwise, if v is < 0 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 duplicate_address
table that would provide the starting index and total length of
the duplicate entries to consider sequentially.

View File

@ -0,0 +1,132 @@
/* Hash table for checking keyword links. Implemented using double hashing.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "hashtable.h"
#include "options.h"
#ifdef GATHER_STATISTICS
/* Find out how well our double hashing is working! */
static collisions = 0;
#endif
/* Locally visible hash table. */
static HASH_TABLE hash_table;
/* Basically the algorithm from the Dragon book. */
static unsigned
hash_pjw (str)
char *str;
{
char *temp;
unsigned g, h = 0;
for (temp = str; *temp; temp++)
{
h = (h << 4) + (*temp * 13);
if (g = h & 0xf0000000)
{
h ^= (g >> 24);
h ^= g;
}
}
return h;
}
/* 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! */
void
hash_table_init (table, s)
LIST_NODE **table;
int s;
{
hash_table.size = s;
hash_table.table = table;
bzero ((char *) hash_table.table, hash_table.size * sizeof *hash_table.table);
}
/* Frees the dynamically allocated table. Note that since we don't
really need this space anymore, and since it is potentially quite
big it is best to return it when we are done. */
void
hash_table_destroy ()
{
if (OPTION_ENABLED (option, DEBUG))
{
int i;
fprintf (stderr, "\ndumping the hash table\ntotal elements = %d, bytes = %d\n",
hash_table.size, hash_table.size * sizeof *hash_table.table);
for (i = hash_table.size - 1; i >= 0; i--)
if (hash_table.table[i])
fprintf (stderr, "location[%d] has charset \"%s\" and keyword \"%s\"\n",
i, hash_table.table[i]->char_set, hash_table.table[i]->key);
#ifdef GATHER_STATISTICS
fprintf (stderr, "\ntotal collisions during hashing = %d\n", collisions);
#endif
fprintf (stderr, "end 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 *
retrieve (item, ignore_length)
LIST_NODE *item;
int ignore_length;
{
unsigned hash_val = hash_pjw (item->char_set);
int probe = hash_val & hash_table.size - 1;
int increment = (hash_val ^ item->length | 1) & hash_table.size - 1;
while (hash_table.table[probe]
&& (strcmp (hash_table.table[probe]->char_set, item->char_set)
|| (!ignore_length && hash_table.table[probe]->length != item->length)))
{
#ifdef GATHER_STATISTICS
collisions++;
#endif
probe = probe + increment & hash_table.size - 1;
}
if (hash_table.table[probe])
return hash_table.table[probe];
else
{
hash_table.table[probe] = item;
return 0;
}
}

View File

@ -0,0 +1,37 @@
/* Hash table used to check for duplicate keyword entries.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _hashtable_h
#define _hashtable_h
#include "keylist.h"
#include "prototype.h"
typedef struct hash_table
{
LIST_NODE **table; /* Vector of pointers to linked lists of List_Node's. */
int size; /* Size of the vector. */
} HASH_TABLE;
extern void hash_table_init P ((LIST_NODE **table, int size));
extern void hash_table_destroy P ((void));
extern LIST_NODE *retrieve P ((LIST_NODE *item, int ignore_length));
#endif /* _hashtable_h */

View File

@ -0,0 +1,106 @@
/* Provides an Iterator for keyword characters.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <ctype.h>
#include "iterator.h"
/* Locally visible ITERATOR object. */
ITERATOR iterator;
/* Constructor for ITERATOR. */
void
iterator_init (s, lo, hi, word_end, bad_val, key_end)
char *s;
int lo;
int hi;
int word_end;
int bad_val;
int key_end;
{
iterator.end = key_end;
iterator.error_value = bad_val;
iterator.end_word = word_end;
iterator.str = s;
iterator.hi_bound = hi;
iterator.lo_bound = lo;
}
/* Define several useful macros to clarify subsequent code. */
#define ISPOSDIGIT(X) ((X)<='9'&&(X)>'0')
#define TODIGIT(X) ((X)-'0')
/* Provide an Iterator, returning the ``next'' value from
the list of valid values given in the constructor. */
int
next ()
{
/* 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 (*iterator.str)
{
if (*iterator.str == ',')
iterator.str++;
else if (*iterator.str == '$')
{
iterator.str++;
return iterator.end_word;
}
else if (ISPOSDIGIT (*iterator.str))
{
for (curr_value = 0; isdigit (*iterator.str); iterator.str++)
curr_value = curr_value * 10 + *iterator.str - '0';
if (*iterator.str == '-')
{
for (size = 1, upper_bound = 0;
isdigit (*++iterator.str);
upper_bound = upper_bound * 10 + *iterator.str - '0');
if (upper_bound <= curr_value || upper_bound > iterator.hi_bound)
return iterator.error_value;
}
return curr_value >= iterator.lo_bound && curr_value <= iterator.hi_bound
? curr_value : iterator.error_value;
}
else
return iterator.error_value;
}
return iterator.end;
}
}

View File

@ -0,0 +1,47 @@
/* Provides an Iterator for keyword characters.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, 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
#include "prototype.h"
typedef struct iterator
{
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. */
} ITERATOR;
extern void iterator_init P ((char *s, int lo, int hi, int word_end, int bad_val, int key_end));
extern int next P ((void));
#endif /* _iterator_h */

1033
contrib/gperf/src/keylist.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
/* Data and function member declarations for the keyword list class.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The key word list is a useful abstraction that keeps track of
various pieces of information that enable that fast generation
of the Perfect.hash function. A Key_List is a singly-linked
list of List_Nodes. */
#ifndef _keylist_h
#define _keylist_h
#include <stdio.h>
#include "listnode.h"
typedef struct key_list
{
LIST_NODE *head; /* Points to the head of the linked list. */
char *array_type; /* Pointer to the type for word list. */
char *return_type; /* Pointer to return type for lookup function. */
char *struct_tag; /* Shorthand for user-defined struct tag type. */
char *include_src; /* C source code to be included verbatim. */
int list_len; /* Length of head's Key_List, not counting duplicates. */
int total_keys; /* Total number of keys, counting duplicates. */
int max_key_len; /* Maximum length of the longest keyword. */
int min_key_len; /* Minimum length of the shortest keyword. */
bool occurrence_sort; /* True if sorting by occurrence. */
bool hash_sort; /* True if sorting by hash value. */
bool additional_code; /* True if any additional C code is included. */
} KEY_LIST;
extern void key_list_init P ((void));
extern void key_list_destroy P ((void));
extern void print_output P ((void));
extern int keyword_list_length P ((void));
extern int max_key_length P ((void));
extern KEY_LIST key_list;
#endif /* _keylist_h */

View File

@ -0,0 +1,111 @@
/* Creates and initializes a new list node.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "options.h"
#include "listnode.h"
#include "stderr.h"
/* See comments in perfect.cc. */
extern int occurrences[ALPHABET_SIZE];
/* Sorts the key set alphabetically to speed up subsequent operations.
Uses insertion sort since the set is probably quite small. */
static void
set_sort (base, len)
char *base;
int len;
{
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 KEY_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. */
LIST_NODE *
make_list_node (k, len)
char *k;
int len;
{
LIST_NODE *buffered_malloc ();
int char_set_size = OPTION_ENABLED (option, ALLCHARS) ? len : GET_CHARSET_SIZE (option) + 1;
LIST_NODE *temp = buffered_malloc (sizeof (LIST_NODE) + char_set_size);
char *ptr = temp->char_set;
k[len] = '\0'; /* Null terminate KEY to separate it from REST. */
temp->key = k;
temp->next = 0;
temp->index = 0;
temp->length = len;
temp->link = 0;
temp->rest = OPTION_ENABLED (option, TYPE) ? k + len + 1 : "";
if (OPTION_ENABLED (option, ALLCHARS)) /* Use all the character position in the KEY. */
for (; *k; k++, ptr++)
++occurrences[*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 temp->char_set (via char * pointer ptr). */
for(RESET (option); (i = GET (option)) != EOS; )
{
if (i == WORD_END) /* Special notation for last KEY position, i.e. '$'. */
*ptr = temp->key[len - 1];
else if (i <= len) /* Within range of KEY length, so we'll keep it. */
*ptr = temp->key[i - 1];
else /* Out of range of KEY length, so we'll just skip it. */
continue;
++occurrences[*ptr++];
}
if (ptr == temp->char_set) /* Didn't get any hits, i.e., no usable positions. */
report_error ("can't hash keyword %s with chosen key positions\n%a", temp->key);
}
*ptr = '\0'; /* Terminate this bastard.... */
/* Sort the KEY_SET items alphabetically. */
set_sort (temp->char_set, ptr - temp->char_set);
return temp;
}

View File

@ -0,0 +1,43 @@
/* Data and function members for defining values and operations of a list node.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _listnode_h
#define _listnode_h
#include "prototype.h"
#define ALPHABET_SIZE 128
typedef struct list_node
{
struct list_node *link; /* TRUE if key has an identical KEY_SET as another key. */
struct list_node *next; /* Points to next element on the list. */
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. */
char *key; /* Key string. */
char *rest; /* Additional information for building hash function. */
char char_set[1]; /* Set of characters to hash, specified by user. */
} LIST_NODE;
extern LIST_NODE *make_list_node P ((char *k, int len));
#endif _listnode_h

96
contrib/gperf/src/main.c Normal file
View File

@ -0,0 +1,96 @@
/* Driver program for the Perfect hash function generator.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Simple driver program for the Perfect.hash function generator.
Most of the hard work is done in class Perfect and its class methods. */
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include "stderr.h"
#include "options.h"
#include "perfect.h"
/* Calls the appropriate intialization routines for each
ADT. Note that certain initialization routines require
initialization *after* certain values are computed. Therefore,
they cannot be called here. */
static void
init_all (argc, argv)
int argc;
char *argv[];
{
#ifdef RLIMIT_STACK
/* Get rid of any avoidable limit on stack size. */
{
struct rlimit rlim;
/* Set the stack limit huge so that alloca does not fail. */
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = rlim.rlim_max;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif /* RLIMIT_STACK */
options_init (argc, argv);
key_list_init ();
perfect_init ();
}
/* Calls appropriate destruction routines for each ADT. These
routines print diagnostics if the debugging option is enabled. */
static void
destroy_all ()
{
options_destroy ();
key_list_destroy ();
perfect_destroy ();
}
/* Driver for perfect hash function generation. */
int
main (argc, argv)
int argc;
char *argv[];
{
struct tm *tm;
time_t clock;
int status;
time (&clock);
tm = localtime (&clock);
fprintf (stderr, "/* starting time is %d:%d:%d */\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
/* Sets the options. */
init_all (argc, argv);
/* Generates the perfect hash table.
Also prints generated code neatly to the output. */
status = perfect_generate ();
destroy_all ();
time (&clock);
tm = localtime (&clock);
fprintf (stderr, "/* ending time is %d:%d:%d */\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
return status;
}

444
contrib/gperf/src/options.c Normal file
View File

@ -0,0 +1,444 @@
/* Handles parsing the Options provided to the user.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <assert.h>
#include "options.h"
#include "iterator.h"
#include "stderr.h"
/* Current program version. */
extern char *version_string;
/* Size to jump on a collision. */
#define DEFAULT_JUMP_VALUE 5
/* Default name for generated lookup function. */
#define DEFAULT_NAME "in_word_set"
/* Default name for the key component. */
#define DEFAULT_KEY "name"
/* Default name for generated hash function. */
#define DEFAULT_HASH_NAME "hash"
/* Globally visible OPTIONS object. */
OPTIONS option;
/* Default delimiters that separate keywords from their attributes. */
#define DEFAULT_DELIMITERS ",\n"
/* Prints program usage to standard error stream. */
void
usage ()
{
report_error ("usage: %n [-acCdDef[num]gGhH<hashname>i<init>jk<keys>\
K<keyname>lnN<name>oprs<size>S<switches>tTv].\n(type %n -h for help)\n");
}
/* 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. */
static int
key_sort (base, len)
char *base;
int len;
{
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;
}
/* Dumps option status when debug is set. */
void
options_destroy ()
{
if (OPTION_ENABLED (option, DEBUG))
{
char *ptr;
fprintf (stderr, "\ndumping Options:\nDEBUG is.......: %s\nORDER is.......: %s\
\nANSI is........: %s\nTYPE is........: %s\nGNU is.........: %s\nRANDOM is......: %s\
\nDEFAULTCHARS is: %s\nSWITCH is......: %s\nPOINTER is.....: %s\nNOLENGTH is....: %s\
\nLENTABLE is....: %s\nDUP is.........: %s\nCOMP is........: %s\nFAST is........: %s\
\nNOTYPE is......: %s\nGLOBAL is......: %s\nCONST is.......: %s\niterations = %d\
\nlookup function name = %s\nhash function name = %s\nkey name = %s\
\njump value = %d\nmax associcated value = %d\ninitial associated value = %d\
\ndelimiters = %s\nnumber of switch statements = %d\napproximate switch statement size = %d\n",
OPTION_ENABLED (option, DEBUG) ? "enabled" : "disabled",
OPTION_ENABLED (option, ORDER) ? "enabled" : "disabled",
OPTION_ENABLED (option, ANSI) ? "enabled" : "disabled",
OPTION_ENABLED (option, TYPE) ? "enabled" : "disabled",
OPTION_ENABLED (option, GNU) ? "enabled" : "disabled",
OPTION_ENABLED (option, RANDOM) ? "enabled" : "disabled",
OPTION_ENABLED (option, DEFAULTCHARS) ? "enabled" : "disabled",
OPTION_ENABLED (option, SWITCH) ? "enabled" : "disabled",
OPTION_ENABLED (option, POINTER) ? "enabled" : "disabled",
OPTION_ENABLED (option, NOLENGTH) ? "enabled" : "disabled",
OPTION_ENABLED (option, LENTABLE) ? "enabled" : "disabled",
OPTION_ENABLED (option, DUP) ? "enabled" : "disabled",
OPTION_ENABLED (option, COMP) ? "enabled" : "disabled",
OPTION_ENABLED (option, FAST) ? "enabled" : "disabled",
OPTION_ENABLED (option, NOTYPE) ? "enabled" : "disabled",
OPTION_ENABLED (option, GLOBAL) ? "enabled" : "disabled",
OPTION_ENABLED (option, CONST) ? "enabled" : "disabled",
option.iterations, option.function_name, option.hash_name,
option.key_name, option.jump, option.size - 1,
option.initial_asso_value, option.delimiters, option.total_switches,
keyword_list_length () / option.total_switches);
if (OPTION_ENABLED (option, ALLCHARS))
fprintf (stderr, "all characters are used in the hash function\n");
fprintf (stderr, "maximum charset size = %d\nkey positions are: \n",
option.total_charset_size);
for (ptr = option.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.option_word. */
void
options_init (argc, argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
int option_char;
option.key_positions[0] = WORD_START;
option.key_positions[1] = WORD_END;
option.key_positions[2] = EOS;
option.total_charset_size = 2;
option.jump = DEFAULT_JUMP_VALUE;
option.option_word = (int) DEFAULTCHARS;
option.function_name = DEFAULT_NAME;
option.hash_name = DEFAULT_HASH_NAME;
option.key_name = DEFAULT_KEY;
option.delimiters = DEFAULT_DELIMITERS;
option.initial_asso_value = option.size = option.iterations = 0;
option.total_switches = 1;
option.argument_count = argc;
option.argument_vector = argv;
set_program_name (argv[0]);
while ((option_char = getopt (argc, argv, "adcCDe:f:gGhH:i:j:k:K:lnN:oprs:S:tTv")) != EOF)
{
switch (option_char)
{
case 'a': /* Generated coded uses the ANSI prototype format. */
{
SET_OPTION (option, ANSI);
break;
}
case 'c': /* Generate strncmp rather than strcmp. */
{
SET_OPTION (option, COMP);
break;
}
case 'C': /* Make the generated tables readonly (const). */
{
SET_OPTION (option, CONST);
break;
}
case 'd': /* Enable debugging option. */
{
SET_OPTION (option, DEBUG);
report_error ("starting program %n, version %s, with debuggin on.\n",
version_string);
break;
}
case 'D': /* Enable duplicate option. */
{
SET_OPTION (option, DUP);
break;
}
case 'e': /* Allows user to provide keyword/attribute separator */
{
SET_DELIMITERS (option, optarg);
break;
}
case 'f': /* Generate the hash table ``fast.'' */
{
SET_OPTION (option, FAST);
if ((option.iterations = atoi (optarg)) < 0)
{
report_error ("iterations value must not be negative, assuming 0\n");
option.iterations = 0;
}
break;
}
case 'g': /* Use the ``inline'' keyword for generated sub-routines. */
{
SET_OPTION (option, GNU);
break;
}
case 'G': /* Make the keyword table a global variable. */
{
SET_OPTION (option, GLOBAL);
break;
}
case 'h': /* Displays a list of helpful Options to the user. */
{
report_error (
"-a\tGenerate ANSI standard C output code, i.e., function prototypes.\n\
-c\tGenerate comparison code using strncmp rather than strcmp.\n\
-C\tMake the contents of generated lookup tables constant, i.e., readonly.\n\
-d\tEnables the debugging option (produces verbose output to Std_Err).\n\
-D\tHandle keywords that hash to duplicate values. This is useful\n\
\tfor certain highly redundant keyword sets. It enables the -S option.\n\
-e\tAllow user to provide a string containing delimiters used to separate\n\
\tkeywords from their attributes. Default is \",\\n\"\n\
-f\tGenerate the perfect hash function ``fast.'' This decreases GPERF's\n\
\trunning time at the cost of minimizing generated table-size.\n\
\tThe numeric argument represents the number of times to iterate when\n\
\tresolving a collision. `0' means ``iterate by the number of keywords''.\n\
-g\tAssume a GNU compiler, e.g., g++ or gcc. This makes all generated\n\
\troutines use the ``inline'' keyword to remove cost of function calls.\n\
-G\tGenerate the static table of keywords as a static global variable,\n\
\trather than hiding it inside of the lookup function (which is the\n\
\tdefault behavior).\n\
-h\tPrints this mesage.\n");
report_error (
"-H\tAllow user to specify name of generated hash function. Default is `hash'.\n\
-i\tProvide an initial value for the associate values array. Default is 0.\n\
\tSetting this value larger helps inflate the size of the final table.\n\
-j\tAffects the ``jump value,'' i.e., how far to advance the associated\n\
\tcharacter value upon collisions. Must be an odd number, default is %d.\n\
-k\tAllows selection of the key positions used in the hash function.\n\
\tThe allowable choices range between 1-%d, inclusive. The positions\n\
\tare separated by commas, ranges may be used, and key positions may\n\
\toccur in any order. Also, the meta-character '*' causes the generated\n\
\thash function to consider ALL key positions, and $ indicates the\n\
\t``final character'' of a key, e.g., $,1,2,4,6-10.\n\
-K\tAllow user to select name of the keyword component in the keyword structure.\n\
-l\tCompare key lengths before trying a string comparison. This helps\n\
\tcut down on the number of string comparisons made during the lookup.\n\
-n\tDo not include the length of the keyword when computing the hash function\n\
-N\tAllow user to specify name of generated lookup function. Default\n\
\tname is `in_word_set.'\n\
-o\tReorders input keys by frequency of occurrence of the key sets.\n\
\tThis should decrease the search time dramatically.\n\
-p\tChanges the return value of the generated function ``in_word_set''\n\
\tfrom its default boolean value (i.e., 0 or 1), to type ``pointer\n\
\tto wordlist array'' This is most useful when the -t option, allowing\n\
\tuser-defined structs, is used.\n",
DEFAULT_JUMP_VALUE, MAX_KEY_POS - 1);
report_error (
"-r\tUtilizes randomness to initialize the associated values table.\n\
-s\tAffects the size of the generated hash table. The numeric argument\n\
\tfor this option indicates ``how many times larger'' the table range\n\
\tshould be, in relationship to the number of keys, e.g. a value of 3\n\
\tmeans ``make the table about 3 times larger than the number of input\n\
\tkeys.'' A larger table should decrease the time required for an\n\
\tunsuccessful search, at the expense of extra table space. Default\n\
\tvalue is 1. This actual table size may vary somewhat.\n\
-S\tCauses the generated C code to use a switch statement scheme, rather\n\
\tthan an array lookup table. This can lead to a reduction in both\n\
\ttime and space requirements for some keyfiles. The argument to\n\
\tthis option determines how many switch statements are generated.\n\
\tA value of 1 generates 1 switch containing all the elements, a value of 2\n\
\tgenerates 2 tables with 1/2 the elements in each table, etc. This\n\
\tis useful since many C compilers cannot correctly generate code for\n\
\tlarge switch statements.\n\
\tthe expense of longer time for each lookup. Mostly important for\n\
\t*large* input sets, i.e., greater than around 100 items or so.\n\
-t\tAllows the user to include a structured type declaration for \n\
\tgenerated code. Any text before %%%% is consider part of the type\n\
\tdeclaration. Key words and additional fields may follow this, one\n\
\tgroup of fields per line.\n\
-T\tPrevents the transfer of the type declaration to the output file.\n\
\tUse this option if the type is already defined elsewhere.\n\
-v\tPrints out the current version number\n%e%a\n",
usage);
}
case 'H': /* Sets the name for the hash function */
{
option.hash_name = optarg;
break;
}
case 'i': /* Sets the initial value for the associated values array. */
{
if ((option.initial_asso_value = atoi (optarg)) < 0)
report_error ("initial value %d must be non-zero, ignoring and continuing\n",
option.initial_asso_value);
if (OPTION_ENABLED (option, RANDOM))
report_error ("warning, -r option superceeds -i, ignoring -i option and continuing\n");
break;
}
case 'j': /* Sets the jump value, must be odd for later algorithms. */
{
if ((option.jump = atoi (optarg)) < 0)
report_error ("jump value %d must be a positive number\n%e%a",
option.jump, usage);
else if (option.jump && EVEN (option.jump))
report_error ("jump value %d should be odd, adding 1 and continuing...\n",
option.jump++);
break;
}
case 'k': /* Sets key positions used for hash function. */
{
int BAD_VALUE = -1;
int value;
iterator_init (optarg, 1, MAX_KEY_POS - 1, WORD_END, BAD_VALUE, EOS);
if (*optarg == '*') /* Use all the characters for hashing!!!! */
{
UNSET_OPTION (option, DEFAULTCHARS);
SET_OPTION (option, ALLCHARS);
}
else
{
char *key_pos;
for (key_pos = option.key_positions; (value = next ()) != EOS; key_pos++)
if (value == BAD_VALUE)
report_error ("illegal key value or range, use 1,2,3-%d,'$' or '*'.\n%e%a",
(MAX_KEY_POS - 1),usage);
else
*key_pos = value;;
*key_pos = EOS;
if (! (option.total_charset_size = (key_pos - option.key_positions)))
report_error ("no keys selected\n%e%a", usage);
else if (! key_sort (option.key_positions, option.total_charset_size))
report_error ("duplicate keys selected\n%e%a", usage);
if (option.total_charset_size != 2
|| (option.key_positions[0] != 1 || option.key_positions[1] != WORD_END))
UNSET_OPTION (option, DEFAULTCHARS);
}
break;
}
case 'K': /* Make this the keyname for the keyword component field. */
{
option.key_name = optarg;
break;
}
case 'l': /* Create length table to avoid extra string compares. */
{
SET_OPTION (option, LENTABLE);
break;
}
case 'n': /* Don't include the length when computing hash function. */
{
SET_OPTION (option, NOLENGTH);
break;
}
case 'N': /* Make generated lookup function name be optarg */
{
option.function_name = optarg;
break;
}
case 'o': /* Order input by frequency of key set occurrence. */
{
SET_OPTION (option, ORDER);
break;
}
case 'p': /* Generated lookup function now a pointer instead of int. */
{
SET_OPTION (option, POINTER);
break;
}
case 'r': /* Utilize randomness to initialize the associated values table. */
{
SET_OPTION (option, RANDOM);
if (option.initial_asso_value != 0)
report_error ("warning, -r option superceeds -i, disabling -i option and continuing\n");
break;
}
case 's': /* Range of associated values, determines size of final table. */
{
if ((option.size = atoi (optarg)) <= 0)
report_error ("improper range argument %s\n%e%a", optarg, usage);
else if (option.size > 50)
report_error ("%d is excessive, did you really mean this?! (type %n -h for help)\n",
option.size);
break;
}
case 'S': /* Generate switch statement output, rather than lookup table. */
{
SET_OPTION (option, SWITCH);
if ((option.total_switches = atoi (optarg)) <= 0)
report_error ("number of switches %s must be a positive number\n%e%a", optarg, usage);
break;
}
case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */
{
SET_OPTION (option, TYPE);
break;
}
case 'T': /* Don't print structure definition. */
{
SET_OPTION (option, NOTYPE);
break;
}
case 'v': /* Print out the version and quit. */
report_error ("%n: version %s\n%e%a\n", version_string, usage);
default:
report_error ("%e%a", usage);
}
}
if (argv[optind] && ! freopen (argv[optind], "r", stdin))
report_error ("unable to read key word file %s\n%e%a", argv[optind], usage);
if (++optind < argc)
report_error ("extra trailing arguments to %n\n%e%a", usage);
}
/* Output command-line Options. */
void
print_options ()
{
int i;
printf ("/* Command-line: ");
for (i = 0; i < option.argument_count; i++)
printf ("%s ", option.argument_vector[i]);
printf (" */\n\n");
}

153
contrib/gperf/src/options.h Normal file
View File

@ -0,0 +1,153 @@
/* Handles parsing the Options provided to the user.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This module provides a uniform interface to the various Options available
to a user of the Perfect.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
#include <stdio.h>
#include "prototype.h"
/* Enumerate the potential debugging Options. */
enum option_type
{
DEBUG = 01, /* Enable debugging (prints diagnostics to Std_Err). */
ORDER = 02, /* Apply ordering heuristic to speed-up search time. */
ANSI = 04, /* Generate ANSI prototypes. */
ALLCHARS = 010, /* Use all characters in hash function. */
GNU = 020, /* Assume GNU extensions (primarily function inline). */
TYPE = 040, /* Handle user-defined type structured keyword input. */
RANDOM = 0100, /* Randomly initialize the associated values table. */
DEFAULTCHARS = 0200, /* Make default char positions be 1,$ (end of keyword). */
SWITCH = 0400, /* Generate switch output to save space. */
POINTER = 01000, /* Have in_word_set function return pointer, not boolean. */
NOLENGTH = 02000, /* Don't include keyword length in hash computations. */
LENTABLE = 04000, /* Generate a length table for string comparison. */
DUP = 010000, /* Handle duplicate hash values for keywords. */
FAST = 020000, /* Generate the hash function ``fast.'' */
NOTYPE = 040000, /* Don't include user-defined type definition
in output -- it's already defined elsewhere. */
COMP = 0100000, /* Generate strncmp rather than strcmp. */
GLOBAL = 0200000, /* Make the keyword table a global variable. */
CONST = 0400000, /* Make the generated tables readonly (const). */
};
/* Define some useful constants. */
/* Max size of each word's key set. */
#define MAX_KEY_POS (128 - 1)
/* Signals the start of a word. */
#define WORD_START 1
/* Signals the end of a word. */
#define WORD_END 0
/* Signals end of the key list. */
#define EOS MAX_KEY_POS
/* Returns TRUE if option O is enabled. */
#define OPTION_ENABLED(OW,O) (OW.option_word & (int)O)
/* Enables option O in OPTION_WORD. */
#define SET_OPTION(OW,O) (OW.option_word |= (int)O)
/* Disable option O in OPTION_WORD. */
#define UNSET_OPTION(OW,O) (OW.option_word &= ~(int)(O))
/* Returns total distinct key positions. */
#define GET_CHARSET_SIZE(O) (O.total_charset_size)
/* Set the total distinct key positions. */
#define SET_CHARSET_SIZE(O,S) (O.total_charset_size = (S))
/* Initializes the key Iterator. */
#define RESET(O) (O.key_pos = 0)
/* Returns current key_position and advances index. */
#define GET(O) (O.key_positions[O.key_pos++])
/* Sets the size of the table size. */
#define SET_ASSO_MAX(O,R) (O.size = (R))
/* Returns the size of the table size. */
#define GET_ASSO_MAX(O) (O.size)
/* Returns the jump value. */
#define GET_JUMP(O) (O.jump)
/* Returns the iteration value. */
#define GET_ITERATIONS(O) (O.iterations)
/* Returns the lookup function name. */
#define GET_FUNCTION_NAME(O) (O.function_name)
/* Returns the keyword key name. */
#define GET_KEY_NAME(O) (O.key_name)
/* Returns the hash function name. */
#define GET_HASH_NAME(O) (O.hash_name)
/* Returns the initial associated character value. */
#define INITIAL_VALUE(O) (O.initial_asso_value)
/* Returns the string used to delimit keywords from other attributes. */
#define GET_DELIMITER(O) (O.delimiters)
/* Sets the keyword/attribute delimiters with value of D. */
#define SET_DELIMITERS(O,D) (O.delimiters = (D))
/* Gets the total number of switch statements to generate. */
#define GET_TOTAL_SWITCHES(O) (O.total_switches)
/* Class manager for gperf program options. */
typedef struct options
{
int option_word; /* Holds the user-specified Options. */
int total_charset_size; /* Total number of distinct key_positions. */
int size; /* Range of the hash table. */
int key_pos; /* Tracks current key position for Iterator. */
int jump; /* Jump length when trying alternative values. */
int initial_asso_value; /* Initial value for asso_values table. */
int argument_count; /* Records count of command-line arguments. */
int iterations; /* Amount to iterate when a collision occurs. */
int total_switches; /* Number of switch statements to generate. */
char **argument_vector; /* Stores a pointer to command-line vector. */
char *function_name; /* Name used for generated lookup function. */
char *key_name; /* Name used for keyword key. */
char *hash_name; /* Name used for generated hash function. */
char *delimiters; /* Separates keywords from other attributes. */
char key_positions[MAX_KEY_POS]; /* Contains user-specified key choices. */
} OPTIONS;
extern void options_init P ((int argc, char *argv[]));
extern void options_destroy P ((void));
extern OPTIONS option;
#endif /* _options_h */

350
contrib/gperf/src/perfect.c Normal file
View File

@ -0,0 +1,350 @@
/* Provides high-level routines to manipulate the keywork list
structures the code generation output.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include "options.h"
#include "perfect.h"
#include "stderr.h"
/* Current release version. */
extern char *version_string;
/* Counts occurrences of each key set character. */
int occurrences[ALPHABET_SIZE];
/* Value associated with each character. */
int asso_values[ALPHABET_SIZE];
/* Locally visible PERFECT object. */
PERFECT perfect;
/* 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! */
void
perfect_init ()
{
int asso_value_max;
int len;
perfect.num_done = 1;
perfect.fewest_collisions = 0;
read_keys ();
if (OPTION_ENABLED (option, ORDER))
reorder ();
asso_value_max = GET_ASSO_MAX (option);
len = keyword_list_length ();
asso_value_max = (asso_value_max ? asso_value_max * len : len);
SET_ASSO_MAX (option, POW (asso_value_max));
if (OPTION_ENABLED (option, RANDOM))
{
int i;
srandom (time (0));
for (i = 0; i < ALPHABET_SIZE; i++)
asso_values[i] = (random () & asso_value_max - 1);
}
else
{
int asso_value = INITIAL_VALUE (option);
if (asso_value) /* Initialize array if user requests non-zero default. */
{
int i;
for (i = ALPHABET_SIZE - 1; i >= 0; i--)
asso_values[i] = asso_value & GET_ASSO_MAX (option) - 1;
}
}
perfect.max_hash_value = max_key_length () + GET_ASSO_MAX (option) *
GET_CHARSET_SIZE (option);
printf ("/* C code produced by gperf version %s */\n", version_string);
print_options ();
if (OPTION_ENABLED (option, DEBUG))
{
int i;
fprintf (stderr, "\nnumber of keys = %d\nmaximum associated value is %d\
\nmaximum possible size of generated hash table is %d\n",
len, asso_value_max, perfect.max_hash_value);
}
}
/* Merge two 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. */
static int
compute_disjoint_union (set_1, set_2, set_3)
char *set_1;
char *set_2;
char *set_3;
{
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. */
static void
sort_set (union_set, len)
char *union_set;
int len;
{
int i, j;
for (i = 0, j = len - 1; i < j; i++)
{
char curr, tmp;
for (curr = i+1, tmp = union_set[curr];
curr > 0 && occurrences[tmp] < occurrences[union_set[curr-1]];
curr--)
union_set[curr] = union_set[curr - 1];
union_set[curr] = tmp;
}
}
/* Generate a key set's hash value. */
static int
hash (key_node)
LIST_NODE *key_node;
{
int sum = OPTION_ENABLED (option, NOLENGTH) ? 0 : key_node->length;
char *ptr;
for (ptr = key_node->char_set; *ptr; ptr++)
sum += asso_values[*ptr];
return key_node->hash_value = sum;
}
/* Find out how associated value changes affect successfully hashed items.
Returns FALSE if no other hash values are affected, else returns TRUE.
Note that because GET_ASSO_MAX (option) is a power of two we can guarantee
that all legal ASSO_VALUES are visited without repetition since
GET_JUMP (option) was forced to be an odd value! */
static bool
affects_prev (c, curr)
char c;
LIST_NODE *curr;
{
int original_char = asso_values[c];
int i = !OPTION_ENABLED (option, FAST) ? GET_ASSO_MAX (option) :
GET_ITERATIONS (option) == 0 ? key_list.list_len : GET_ITERATIONS (option);
/* Try all asso_values. */
while (--i >= 0)
{
int collisions = 0;
LIST_NODE *ptr;
asso_values[c] = asso_values[c] + (GET_JUMP (option) ? GET_JUMP (option) : random ())
& GET_ASSO_MAX (option) - 1;
bool_array_reset ();
/* See how this asso_value change affects previous keywords. If
it does better than before we'll take it! */
for (ptr = key_list.head;
!lookup (hash (ptr)) || ++collisions < perfect.fewest_collisions;
ptr = ptr->next)
if (ptr == curr)
{
perfect.fewest_collisions = collisions;
return FALSE;
}
}
asso_values[c] = original_char; /* Restore original values, no more tries. */
return TRUE; /* If we're this far it's time to try the next character.... */
}
/* Change a character value, try least-used characters first. */
static void
change (prior, curr)
LIST_NODE *prior;
LIST_NODE *curr;
{
char *xmalloc ();
static char *union_set = 0;
char *temp;
LIST_NODE *ptr;
if (!union_set)
union_set = xmalloc (2 * GET_CHARSET_SIZE (option) + 1);
if (OPTION_ENABLED (option, DEBUG)) /* Very useful for debugging. */
{
fprintf (stderr, "collision on keyword #%d, prior=\"%s\", curr=\"%s\", hash=%d\n",
perfect.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. */
perfect.fewest_collisions++;
for (temp = union_set; *temp; temp++)
if (!affects_prev (*temp, curr))
{
if (OPTION_ENABLED (option, DEBUG))
{
fprintf (stderr, "- resolved by changing asso_value['%c'] (char #%d) to %d\n",
*temp, temp - union_set + 1, asso_values[*temp]);
fflush (stderr);
}
return; /* Good, doesn't affect previous hash values, we'll take it. */
}
for (ptr = key_list.head; ptr != curr; ptr = ptr->next)
hash (ptr);
hash (curr);
if (OPTION_ENABLED (option, DEBUG))
{
fprintf (stderr, "** collision not resolved, %d duplicates remain, continuing...\n",
perfect.fewest_collisions);
fflush (stderr);
}
}
/* Does the hard stuff....
Initializes the Iteration Number boolean array, and then trys 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
perfect_generate ()
{
LIST_NODE *curr;
bool_array_init (perfect.max_hash_value);
for (curr = key_list.head; curr; curr = curr->next)
{
LIST_NODE *ptr;
hash (curr);
for (ptr = key_list.head; ptr != curr; ptr = ptr->next)
if (ptr->hash_value == curr->hash_value)
{
change (ptr, curr);
break;
}
perfect.num_done++;
}
/* Make one final check, just to make sure nothing weird happened.... */
bool_array_reset ();
for (curr = key_list.head; curr; curr = curr->next)
if (lookup (hash (curr)))
if (OPTION_ENABLED (option, DUP)) /* We'll try to deal with this later..... */
break;
else /* Yow, big problems. we're outta here! */
{
report_error ("\nInternal error, duplicate value %d:\n\
try options -D or -r, or use new key positions.\n\n",
hash (curr));
return 1;
}
bool_array_destroy ();
/* First sorts the key word list by hash value, and the outputs the
list to the proper ostream. The generated hash table code is only
output if the early stage of processing turned out O.K. */
sort ();
print_output ();
return 0;
}
/* Prints out some diagnostics upon completion. */
void
perfect_destroy ()
{
if (OPTION_ENABLED (option, DEBUG))
{
int i;
fprintf (stderr, "\ndumping occurrence and associated values tables\n");
for (i = 0; i < ALPHABET_SIZE; i++)
if (occurrences[i])
fprintf (stderr, "asso_values[%c] = %3d, occurrences[%c] = %3d\n",
i, asso_values[i], i, occurrences[i]);
fprintf (stderr, "end table dumping\n");
}
}

View File

@ -0,0 +1,45 @@
/* Provides high-level routines to manipulate the keyword list
structures the code generation output.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _perfect_h
#define _perfect_h
#include "prototype.h"
#include "keylist.h"
#include "boolarray.h"
typedef struct perfect
{
KEY_LIST list; /* List of key words provided by the user. */
BOOL_ARRAY duplicate; /* Speeds up check for redundant hash values. */
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. */
} PERFECT;
extern void perfect_init P ((void));
extern void perfect_destroy P ((void));
extern int perfect_generate P ((void));
extern void perfect_print P ((void));
#endif /* _perfect_h */

View File

@ -0,0 +1,15 @@
#ifndef _prototype_h
#define _prototype_h
#ifdef __STDC__
#define P(X) X
#else
#define P(X) ()
#endif
typedef char bool;
#define FALSE 0
#define TRUE 1
#define ODD(X) ((X) & 1)
#define EVEN(X) (!((X) & 1))
#endif /* _prototype_h */

View File

@ -0,0 +1,87 @@
/* Correctly reads an arbitrarily size string.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "readline.h"
/* Size of each chunk. */
#define CHUNK_SIZE BUFSIZ
/* Recursively fills up the buffer. */
static char *
readln_aux (chunks)
int chunks;
{
char *buffered_malloc ();
char buf[CHUNK_SIZE];
register char *bufptr = buf;
register char *ptr;
int c;
while ((c = getchar ()) != EOF && c != '\n') /* fill the current buffer */
{
*bufptr++ = c;
if (bufptr - buf >= CHUNK_SIZE) /* prepend remainder to ptr buffer */
{
if (ptr = readln_aux (chunks + 1))
for (; bufptr != buf; *--ptr = *--bufptr);
return ptr;
}
}
if (c == EOF && bufptr == buf)
return NULL;
c = (chunks * CHUNK_SIZE + bufptr - buf) + 1;
if (ptr = buffered_malloc (c))
{
for (*(ptr += (c - 1)) = '\0'; bufptr != buf; *--ptr = *--bufptr)
;
return ptr;
}
else
return NULL;
}
/* Returns the ``next'' line, ignoring comments beginning with '#'. */
char *read_line ()
{
int c;
if ((c = getchar ()) == '#')
{
while ((c = getchar ()) != '\n' && c != EOF)
;
return c != EOF ? read_line () : NULL;
}
else
{
ungetc (c, stdin);
return readln_aux (0);
}
}

View File

@ -0,0 +1,31 @@
/* Reads arbitrarily long string from input file, returning it as a dynamic buffer.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, 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 _readline_h
#define _readline_h
#include "prototype.h"
extern char *read_line P ((void));
#endif /* _readline_h */

View File

@ -0,0 +1,90 @@
/* Provides a useful variable-length argument error handling abstraction.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "stderr.h"
/* Holds the name of the currently active program. */
static char *program_name;
/* Sets name of program. */
void
set_program_name (prog_name)
char *prog_name;
{
program_name = prog_name;
}
/* Valid Options (prefixed by '%', as in printf format strings) include:
'a': exit the program at this point
'c': print a character
'd': print a decimal number
'e': call the function pointed to by the corresponding argument
'f','g': print a double
'n': print the name of the program (NULL if not set in constructor or elsewhere)
'p': print out the appropriate errno value from sys_errlist
's': print out a character string
'%': print out a single percent sign, '%' */
void
report_error (va_alist)
va_dcl
{
extern int errno, sys_nerr;
extern char *sys_errlist[];
typedef void (*PTF)();
typedef char *CHARP;
va_list argp;
int abort = 0;
char *format;
va_start (argp);
for (format = va_arg (argp, char *); *format; format++)
{
if (*format != '%')
putc (*format, stderr);
else
{
switch(*++format)
{
case '%' : putc ('%', stderr); break;
case 'a' : abort = 1; break;
case 'c' : putc (va_arg (argp, int), stderr); break;
case 'd' : fprintf (stderr, "%d", va_arg (argp, int)); break;
case 'e' : (*va_arg (argp, PTF))(); break;
case 'f' : fprintf (stderr, "%g", va_arg (argp, double)); break;
case 'n' : fputs (program_name ? program_name : "error", stderr); break;
case 'p' :
if (errno < sys_nerr)
fprintf (stderr, "%s: %s", va_arg (argp, CHARP), sys_errlist[errno]);
else
fprintf (stderr, "<unknown error> %d", errno);
break;
case 's' : fputs (va_arg (argp, CHARP), stderr); break;
}
}
if (abort)
exit (1);
}
va_end (argp);
}

View File

@ -0,0 +1,29 @@
/* Provides a useful variable-length argument error handling abstraction.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _stderr_h
#define _stderr_h
#include "prototype.h"
#include <varargs.h>
extern void set_program_name P ((char *prog_name));
extern void report_error ();
#endif /* _stderr_h */

View File

@ -0,0 +1,22 @@
/* Current program version number.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
char *version_string = "2.1 (K&R C version)";

View File

@ -0,0 +1,78 @@
/* Provide a useful malloc sanity checker and an efficient buffered memory
allocator that reduces calls to malloc.
Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
/* Grabs SIZE bytes of dynamic memory or dies trying! */
char *
xmalloc (size)
int size;
{
char *malloc ();
char *temp = malloc (size);
if (temp == 0)
{
fprintf (stderr, "out of virtual memory\n");
exit (1);
}
return temp;
}
/* 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;};
#define ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
/* Provide an abstraction that cuts down on the number of
calls to MALLOC by buffering the memory pool from which
items are allocated. */
char *
buffered_malloc (size)
int size;
{
char *temp;
static char *buf_start = 0; /* Large array used to reduce calls to NEW. */
static char *buf_end = 0; /* Indicates end of BUF_START. */
static int buf_size = 4 * BUFSIZ; /* Size of buffer pointed to by BUF_START. */
/* 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. Furthermore, as a heuristic, we double the
size of the new buffer! */
if (buf_start + size >= buf_end)
{
buf_size = buf_size * 2 > size ? buf_size * 2 : size;
buf_start = xmalloc (buf_size);
buf_end = buf_start + buf_size;
}
temp = buf_start;
buf_start += size;
return temp;
}

View File

@ -0,0 +1,65 @@
# Copyright (C) 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA.
GPERF = gperf
CC = gcc
all: test
test:
@echo "performing some tests of the perfect hash generator"
$(CC) -c -O test.c
$(GPERF) -p -c -l -S1 -C -o c.gperf > cinset.c
$(CC) -O -o cout cinset.c test.o
@echo "testing ANSI C reserved words, all items should be found in the set"
./cout -v < c.gperf
$(GPERF) -k1,4,'$$' ada.gperf > adainset.c
# double '$$' is only there since make gets confused; program wants only 1 '$'
$(CC) -O -o aout adainset.c test.o
@echo "testing Ada reserved words,all items should be found in the set"
./aout -v < ada.gperf
$(GPERF) -p -D -S1 -k1,'$$' -s 2 -o adapredefined.gperf > preinset.c
$(CC) -O -o preout preinset.c test.o
@echo "testing Ada predefined words, all items should be found in the set"
./preout -v < adapredefined.gperf
$(GPERF) -k1,2,'$$' -o modula3.gperf > m3inset.c
$(CC) -O -o m3out m3inset.c test.o
@echo "testing Modula3 reserved words, all items should be found in the set"
./m3out -v < modula3.gperf
$(GPERF) -o -S1 -p < pascal.gperf > pinset.c
$(CC) -O -o pout pinset.c test.o
@echo "testing Pascal reserved words, all items should be found in the set"
./pout -v < pascal.gperf
$(GPERF) -o -S2 -j1 -D -p -t < c++.gperf > c++inset.c
$(CC) -O -o c++out c++inset.c test.o
@echo "testing C++ reserved words, all items should be found in the set"
tail -47 c++.gperf | ./c++out -v
# these next 5 are demos that show off the generated code
$(GPERF) -p -j1 -g -o -t -N is_reserved_word -k1,3,'$$' c-parse.gperf
$(GPERF) -n -k1-8 -l modula2.gperf
$(GPERF) -p -j 1 -o -a -g -t -k1,4,$$ gplus.gperf
$(GPERF) -D -p -t < c-parse.gperf
$(GPERF) -g -o -j1 -t -p -N is_reserved_word gpc.gperf
# prints out the help message
-$(GPERF) -h
@echo "only if, do, for, case, goto, else, while, and return should be found "
./aout -v < c.gperf
clean:
-rm -f *.o core *~ *inset.c *out #*#

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,49 @@
struct resword {char *name;};
%%
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

View File

@ -0,0 +1,56 @@
%{
/* Command-line: gperf -p -j1 -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,32 @@
/*
Tests the generated perfect has 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 <stdio.h>
#define MAX_LEN 80
#ifdef __STDC__
int in_word_set (char *, unsigned int);
int
main (int argc, char *argv[])
#else
int
main (argc, argv)
int argc;
char *argv[];
#endif
{
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;
}