home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / gperf / part02 < prev    next >
Encoding:
Internet Message Format  |  1989-10-18  |  51.4 KB

  1. Subject:  v20i041:  Perfect hash generator for sets of key words, Part02/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: "Douglas C. Schmidt" <schmidt@glacier.ics.uci.edu>
  7. Posting-number: Volume 20, Issue 41
  8. Archive-name: gperf/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 5)."
  17. # Contents:  cperf/ChangeLog cperf/src/Makefile cperf/src/getopt.c
  18. #   cperf/src/hashtable.c cperf/src/listnode.c cperf/src/options.h
  19. #   cperf/src/perfect.c
  20. # Wrapped by schmidt@crimee.ics.uci.edu on Wed Oct 18 11:43:32 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'cperf/ChangeLog' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'cperf/ChangeLog'\"
  24. else
  25. echo shar: Extracting \"'cperf/ChangeLog'\" \(8012 characters\)
  26. sed "s/^X//" >'cperf/ChangeLog' <<'END_OF_FILE'
  27. XMon Oct 16 19:58:08 1989  Doug Schmidt  (schmidt at glacier.ics.uci.edu)
  28. X
  29. X        * Fixed a number of small bugs kindly brought to my attention by
  30. X          Adam de Boor (bsw!adam@uunet.UU.NET).  Thanks Adam!  In particular,
  31. X          changed the behavior for the -a (ANSI) option so that the
  32. X          generated prototypes use int rather than size_t for the LEN 
  33. X          parameter.  It was too ugly having to #include <stddef.h> all
  34. X          over the place...
  35. X
  36. X        * Added a majorly neat hack to Bool_Array, suggested by rfg.
  37. X          The basic idea was to throw away the Ullman array technique.
  38. X          The Ullman array was used to remove the need to reinitialize all 
  39. X          the Bool_Array elements to zero everytime we needed to determine
  40. X          whether there were duplicate hash values in the keyword list.  
  41. X          The current trick uses an `iteration number' scheme, which takes
  42. X          about 1/3 the space and reduces the overall program running a 
  43. X          time by about 20 percent for large input!  The hack works as 
  44. X          follows:
  45. X          
  46. X          1. Dynamically allocation 1 boolean array of size k.
  47. X          2. Initialize the boolean array to zeros, and consider the first
  48. X             iteration to be iteration 1.
  49. X          2. Then on all subsequent iterations we `reset' the bool array by
  50. X             kicking the iteration count by 1. 
  51. X          3. When it comes time to check whether a hash value is currently
  52. X             in the boolean array we simply check its index location.  If
  53. X             the value stored there is *not* equal to the current iteration
  54. X             number then the item is clearly *not* in the set.  In that
  55. X             case we assign the iteration number to that array's index
  56. X             location for future reference.  Otherwise, if the item at
  57. X             the index location *is* equal to the iteration number we've
  58. X             found a duplicate.  No muss, no fuss!
  59. X
  60. XThu Oct 12 18:08:43 1989  Doug Schmidt  (schmidt at zola.ics.uci.edu)
  61. X
  62. X        * Updated the version number to 1.9.
  63. X
  64. X        * Added support for the -C option.  This makes the contents of
  65. X          all generated tables `readonly'.
  66. X
  67. X        * Changed the handling of generated switches so that there is
  68. X          only one call to str[n]?cmp.  This *greatly* reduces the size of
  69. X          the generated assembly code on all compilers I've seen.
  70. X
  71. X        * Fixed a subtle bug that occurred when the -l and -S option
  72. X          was given.  Code produced looked something like:
  73. X
  74. X          if (len != key_len || !strcmp (s1, resword->name)) return resword;
  75. X
  76. X          which doesn't make any sense.  Clearly, this should be:
  77. X
  78. X          if (len == key_len && !strcmp (s1, resword->name)) return resword;
  79. X
  80. XSat Sep 30 12:55:24 1989  Doug Schmidt  (schmidt at glacier.ics.uci.edu)
  81. X
  82. X        * Fixed a stupid bug in Key_List::print_hash_function that manifested
  83. X          itself if the `-k$' option was given (i.e., only use the key[length]
  84. X          character in the hash function).
  85. X
  86. XMon Jul 24 17:09:46 1989  Doug Schmidt  (schmidt at glacier.ics.uci.edu)
  87. X
  88. X        * Fixed a bug in PRINT_MIN_MAX that resulted in MAX_INT being printed
  89. X          for the MIN_KEY_LEN if there was only 1 keyword in the input file
  90. X          (yeah, that's a pretty unlikely occurrence, I agree!).
  91. X
  92. X        * Fixed PRINT_HASH_FUNCTION and PRINT_LOOKUP_FUNCTION in keylist.c
  93. X          so that the generated functions take an unsigned int length argument.
  94. X          If -a is enabled the prototype is (const char *str, size_t len).
  95. X
  96. XFri Jul 21 13:06:15 1989  Doug Schmidt  (schmidt at zola.ics.uci.edu)
  97. X
  98. X        * Fixed a horrible typo in PRINT_KEYWORD_TABLE in keylist.cc
  99. X          that prevented links from being printed correctly.
  100. X
  101. XSun Jul  9 17:53:28 1989  Doug Schmidt  (schmidt at glacier.ics.uci.edu)
  102. X
  103. X        * Changed the ./tests subdirectory Makefile so that it 
  104. X          uses $(CC) instead of gcc.
  105. X
  106. XSun Jul  2 12:14:04 1989  Doug Schmidt  (schmidt at glacier.ics.uci.edu)
  107. X
  108. X        * Moved comment handling from keylist.c to readline.c.  This
  109. X          simplifies the code and reduces the number of malloc calls.
  110. X
  111. X        * Fixed a number of subtle bugs that occurred when -S was
  112. X          combined with various and sundry options.
  113. X
  114. X        * Added the -G option, that makes the generated keyword table
  115. X          a global static variable, rather than hiding it inside
  116. X          the lookup function.  This allows other functions to directly
  117. X          access the contents in this table.
  118. X
  119. XSat Jul  1 10:12:21 1989  Doug Schmidt  (schmidt at crimee.ics.uci.edu)
  120. X
  121. X        * Added the "#" feature, that allows comments inside the keyword
  122. X          list from the input file.
  123. X          
  124. X        * Also added the -H option (user can give the name of the hash
  125. X          function) and the -T option (prevents the transfer of the type decl
  126. X          to the output file, which is useful if the type is already defined
  127. X          elsewhere).
  128. X
  129. XFri Jun 30 18:22:35 1989  Doug Schmidt  (schmidt at crimee.ics.uci.edu)
  130. X
  131. X        * Added Adam de Boor's changes.  Created an UNSET_OPTION macro.
  132. X
  133. XSat Jun 17 10:56:00 1989  Doug Schmidt  (schmidt at glacier.ics.uci.edu)
  134. X
  135. X        * Modified option.h and option.c so that all mixed operations
  136. X          between integers and enumerals are cast correctly to int.
  137. X          This prevents errors in some brain-damaged C compilers.
  138. X
  139. XFri Jun 16 14:13:15 1989  Doug Schmidt  (schmidt at crimee.ics.uci.edu)
  140. X
  141. X        * Modified the -f (FAST) option.  This now takes an argument.
  142. X          The argument corresponds to the number of iterations used
  143. X          to resolve collisions.  -f 0 uses the length of the
  144. X          keyword list (which is what -f did before).  This makes
  145. X          life much easier when dealing with large keyword files.
  146. X
  147. XWed Jun  7 23:07:13 1989  Doug Schmidt  (schmidt at zola.ics.uci.edu)
  148. X
  149. X        * Updated to version 1.8 in preparation to release to Doug Lea
  150. X          and FSF.
  151. X
  152. X        * Added the -c (comparison) option.  Enabling this
  153. X          will use the strncmp function for string comparisons.
  154. X          The default is to use strcmp.
  155. X
  156. XTue Jun  6 16:32:09 1989  Doug Schmidt  (schmidt at zola.ics.uci.edu)
  157. X
  158. X        * Fixed another stupid typo in xmalloc.c (XMALLOC).  I accidentally
  159. X          left the ANSI-fied prototype in place.  This obviously
  160. X          fails on old-style C compilers.
  161. X
  162. X        * Fixed stupid typos in PRINT_SWITCH from the keylist.c.  This
  163. X          caused the -D option to produce incorrect output when used
  164. X          in conjunction with -p and -t.
  165. X          
  166. X        * Replaced the use of STRCMP with STRNCMP for the generated
  167. X          C output code.          
  168. X
  169. XFri Jun  2 23:16:01 1989  Doug Schmidt  (schmidt at trinite.ics.uci.edu)
  170. X
  171. X        * Added a new function (XMALLOC) and file (xmalloc.c).  All
  172. X          calls to MALLOC were replaced by calls to XMALLOC.  This 
  173. X          will complain when virtual memory runs out (don't laugh, 
  174. X          this has happened!)
  175. X
  176. XThu Jun  1 21:10:10 1989  Doug Schmidt  (schmidt at zola.ics.uci.edu)
  177. X
  178. X        * Fixed a typo in options.c that prevented the -f option
  179. X          from being given on the command-line.
  180. X
  181. XWed May  3 17:48:02 1989  Doug Schmidt  (schmidt at zola.ics.uci.edu)
  182. X
  183. X        * Updated to version 1.7.  This reflects the recent major changes
  184. X          and the new C port.
  185. X
  186. X        * Fixed a typo in perfect.c perfect_destroy that prevented the actual 
  187. X          maximum hash table size from being printed.
  188. X
  189. X        * Added support for the -f option.  This generates the perfect
  190. X          hash function ``fast.''  It reduces the execution time of
  191. X          gperf, at the cost of minimizing the range of hash values.
  192. X
  193. XTue May  2 16:23:29 1989  Doug Schmidt  (schmidt at crimee.ics.uci.edu)
  194. X
  195. X        * Enabled the diagnostics dump if the debugging option is enabled.
  196. X        
  197. X        * Removed all calls to FREE (silly to do this at program termination).
  198. X
  199. X        * Ported gperf to C.  From now on both K&R C and GNU G++ versions
  200. X          will be supported.
  201. X
  202. END_OF_FILE
  203. if test 8012 -ne `wc -c <'cperf/ChangeLog'`; then
  204.     echo shar: \"'cperf/ChangeLog'\" unpacked with wrong size!
  205. fi
  206. # end of 'cperf/ChangeLog'
  207. fi
  208. if test -f 'cperf/src/Makefile' -a "${1}" != "-c" ; then 
  209.   echo shar: Will not clobber existing file \"'cperf/src/Makefile'\"
  210. else
  211. echo shar: Extracting \"'cperf/src/Makefile'\" \(3414 characters\)
  212. sed "s/^X//" >'cperf/src/Makefile' <<'END_OF_FILE'
  213. X# Copyright (C) 1989 Free Software Foundation, Inc.
  214. X# written by Douglas C. Schmidt (schmidt@ics.uci.edu)
  215. X# 
  216. X# This file is part of GNU GPERF.
  217. X# 
  218. X# GNU GPERF is free software; you can redistribute it and/or modify
  219. X# it under the terms of the GNU General Public License as published by
  220. X# the Free Software Foundation; either version 1, or (at your option)
  221. X# any later version.
  222. X# 
  223. X# GNU GPERF is distributed in the hope that it will be useful,
  224. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  225. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  226. X# GNU General Public License for more details.
  227. X# 
  228. X# You should have received a copy of the GNU General Public License
  229. X# along with GNU GPERF; see the file COPYING.  If not, write to
  230. X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  231. X
  232. XCC = cc
  233. XCFLAGS= -O # -g -fstrength-reduce -finline-functions # gcc options 
  234. XOBJS = options.o iterator.o main.o perfect.o keylist.o listnode.o xmalloc.o \
  235. X       hashtable.o boolarray.o readline.o stderr.o version.o getopt.o
  236. XSOURCES = options.c iterator.c main.c perfect.c keylist.c listnode.c xmalloc.c \
  237. X       hashtable.c boolarray.c readline.c stderr.c version.c getopt.c
  238. X
  239. Xall: gperf
  240. X
  241. Xgperf: $(OBJS) 
  242. X    $(CC) $(CFLAGS) -o gperf $(OBJS) $(LIBS)
  243. X
  244. Xclean: 
  245. X    -rm -f *.o core *~ #*#
  246. X
  247. Xrealclean: clean
  248. X    -rm -f gperf
  249. X
  250. X# dependencies
  251. X# DO NOT DELETE THIS LINE -- mkdep uses it.
  252. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
  253. X
  254. Xboolarray.o: boolarray.c /usr/include/stdio.h boolarray.h prototype.h options.h
  255. Xboolarray.o: /usr/include/stdio.h prototype.h
  256. Xgetopt.o: getopt.c /usr/include/stdio.h
  257. Xhashtable.o: hashtable.c /usr/include/stdio.h hashtable.h keylist.h
  258. Xhashtable.o: /usr/include/stdio.h listnode.h prototype.h prototype.h options.h
  259. Xhashtable.o: /usr/include/stdio.h prototype.h
  260. Xiterator.o: iterator.c /usr/include/stdio.h /usr/include/ctype.h iterator.h
  261. Xiterator.o: prototype.h
  262. Xkeylist.o: keylist.c /usr/include/assert.h /usr/include/stdio.h options.h
  263. Xkeylist.o: /usr/include/stdio.h prototype.h readline.h prototype.h keylist.h
  264. Xkeylist.o: /usr/include/stdio.h listnode.h prototype.h hashtable.h keylist.h
  265. Xkeylist.o: prototype.h stderr.h prototype.h /usr/include/varargs.h
  266. Xlistnode.o: listnode.c /usr/include/stdio.h options.h /usr/include/stdio.h
  267. Xlistnode.o: prototype.h listnode.h prototype.h stderr.h prototype.h
  268. Xlistnode.o: /usr/include/varargs.h
  269. Xmain.o: main.c /usr/include/stdio.h stderr.h prototype.h /usr/include/varargs.h
  270. Xmain.o: options.h /usr/include/stdio.h prototype.h perfect.h prototype.h
  271. Xmain.o: keylist.h /usr/include/stdio.h listnode.h prototype.h boolarray.h
  272. Xmain.o: prototype.h
  273. Xoptions.o: options.c /usr/include/stdio.h /usr/include/assert.h options.h
  274. Xoptions.o: /usr/include/stdio.h prototype.h iterator.h prototype.h stderr.h
  275. Xoptions.o: prototype.h /usr/include/varargs.h
  276. Xperfect.o: perfect.c /usr/include/stdio.h /usr/include/assert.h
  277. Xperfect.o: /usr/include/ctype.h options.h /usr/include/stdio.h prototype.h
  278. Xperfect.o: perfect.h prototype.h keylist.h /usr/include/stdio.h listnode.h
  279. Xperfect.o: prototype.h boolarray.h prototype.h stderr.h prototype.h
  280. Xperfect.o: /usr/include/varargs.h
  281. Xreadline.o: readline.c /usr/include/stdio.h readline.h prototype.h
  282. Xstderr.o: stderr.c /usr/include/stdio.h stderr.h prototype.h
  283. Xstderr.o: /usr/include/varargs.h
  284. Xversion.o: version.c
  285. Xxmalloc.o: xmalloc.c /usr/include/stdio.h
  286. X
  287. X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
  288. END_OF_FILE
  289. if test 3414 -ne `wc -c <'cperf/src/Makefile'`; then
  290.     echo shar: \"'cperf/src/Makefile'\" unpacked with wrong size!
  291. fi
  292. # end of 'cperf/src/Makefile'
  293. fi
  294. if test -f 'cperf/src/getopt.c' -a "${1}" != "-c" ; then 
  295.   echo shar: Will not clobber existing file \"'cperf/src/getopt.c'\"
  296. else
  297. echo shar: Extracting \"'cperf/src/getopt.c'\" \(12436 characters\)
  298. sed "s/^X//" >'cperf/src/getopt.c' <<'END_OF_FILE'
  299. X/* Getopt for GNU.
  300. X   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
  301. X
  302. X   This program is free software; you can redistribute it and/or modify
  303. X   it under the terms of the GNU General Public License as published by
  304. X   the Free Software Foundation; either version 1, or (at your option)
  305. X   any later version.
  306. X
  307. X   This program is distributed in the hope that it will be useful,
  308. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  309. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  310. X   GNU General Public License for more details.
  311. X
  312. X   You should have received a copy of the GNU General Public License
  313. X   along with this program; if not, write to the Free Software
  314. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  315. X
  316. X
  317. X
  318. X/* This version of `getopt' appears to the caller like standard Unix `getopt'
  319. X   but it behaves differently for the user, since it allows the user
  320. X   to intersperse the options with the other arguments.
  321. X
  322. X   As `getopt' works, it permutes the elements of `argv' so that,
  323. X   when it is done, all the options precede everything else.  Thus
  324. X   all application programs are extended to handle flexible argument order.
  325. X
  326. X   Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
  327. X   Then the behavior is completely standard.
  328. X
  329. X   GNU application programs can use a third alternative mode in which
  330. X   they can distinguish the relative order of options and other arguments.  */
  331. X
  332. X#include <stdio.h>
  333. X
  334. X#ifdef sparc
  335. X#include <alloca.h>
  336. X#endif
  337. X#ifdef USG
  338. X#define bcopy(s, d, l) memcpy((d), (s), (l))
  339. X#endif
  340. X
  341. X/* For communication from `getopt' to the caller.
  342. X   When `getopt' finds an option that takes an argument,
  343. X   the argument value is returned here.
  344. X   Also, when `ordering' is RETURN_IN_ORDER,
  345. X   each non-option ARGV-element is returned here.  */
  346. X
  347. Xchar *optarg = 0;
  348. X
  349. X/* Index in ARGV of the next element to be scanned.
  350. X   This is used for communication to and from the caller
  351. X   and for communication between successive calls to `getopt'.
  352. X
  353. X   On entry to `getopt', zero means this is the first call; initialize.
  354. X
  355. X   When `getopt' returns EOF, this is the index of the first of the
  356. X   non-option elements that the caller should itself scan.
  357. X
  358. X   Otherwise, `optind' communicates from one call to the next
  359. X   how much of ARGV has been scanned so far.  */
  360. X
  361. Xint optind = 0;
  362. X
  363. X/* The next char to be scanned in the option-element
  364. X   in which the last option character we returned was found.
  365. X   This allows us to pick up the scan where we left off.
  366. X
  367. X   If this is zero, or a null string, it means resume the scan
  368. X   by advancing to the next ARGV-element.  */
  369. X
  370. Xstatic char *nextchar;
  371. X
  372. X/* Callers store zero here to inhibit the error message
  373. X   for unrecognized options.  */
  374. X
  375. Xint opterr = 1;
  376. X
  377. X/* Describe how to deal with options that follow non-option ARGV-elements.
  378. X
  379. X   UNSPECIFIED means the caller did not specify anything;
  380. X   the default is then REQUIRE_ORDER if the environment variable
  381. X   _OPTIONS_FIRST is defined, PERMUTE otherwise.
  382. X
  383. X   REQUIRE_ORDER means don't recognize them as options.
  384. X   Stop option processing when the first non-option is seen.
  385. X   This is what Unix does.
  386. X
  387. X   PERMUTE is the default.  We permute the contents of `argv' as we scan,
  388. X   so that eventually all the options are at the end.  This allows options
  389. X   to be given in any order, even with programs that were not written to
  390. X   expect this.
  391. X
  392. X   RETURN_IN_ORDER is an option available to programs that were written
  393. X   to expect options and other ARGV-elements in any order and that care about
  394. X   the ordering of the two.  We describe each non-option ARGV-element
  395. X   as if it were the argument of an option with character code zero.
  396. X   Using `-' as the first character of the list of option characters
  397. X   requests this mode of operation.
  398. X
  399. X   The special argument `--' forces an end of option-scanning regardless
  400. X   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
  401. X   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
  402. X
  403. Xstatic enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
  404. X
  405. X/* Handle permutation of arguments.  */
  406. X
  407. X/* Describe the part of ARGV that contains non-options that have
  408. X   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
  409. X   `last_nonopt' is the index after the last of them.  */
  410. X
  411. Xstatic int first_nonopt;
  412. Xstatic int last_nonopt;
  413. X
  414. X/* Exchange two adjacent subsequences of ARGV.
  415. X   One subsequence is elements [first_nonopt,last_nonopt)
  416. X    which contains all the non-options that have been skipped so far.
  417. X   The other is elements [last_nonopt,optind), which contains all
  418. X    the options processed since those non-options were skipped.
  419. X
  420. X   `first_nonopt' and `last_nonopt' are relocated so that they describe
  421. X    the new indices of the non-options in ARGV after they are moved.  */
  422. X
  423. Xstatic void
  424. Xexchange (argv)
  425. X     char **argv;
  426. X{
  427. X  int nonopts_size
  428. X    = (last_nonopt - first_nonopt) * sizeof (char *);
  429. X  char **temp = (char **) alloca (nonopts_size);
  430. X
  431. X  /* Interchange the two blocks of data in argv.  */
  432. X
  433. X  bcopy (&argv[first_nonopt], temp, nonopts_size);
  434. X  bcopy (&argv[last_nonopt], &argv[first_nonopt],
  435. X     (optind - last_nonopt) * sizeof (char *));
  436. X  bcopy (temp, &argv[first_nonopt + optind - last_nonopt],
  437. X     nonopts_size);
  438. X
  439. X  /* Update records for the slots the non-options now occupy.  */
  440. X
  441. X  first_nonopt += (optind - last_nonopt);
  442. X  last_nonopt = optind;
  443. X}
  444. X
  445. X/* Scan elements of ARGV (whose length is ARGC) for option characters
  446. X   given in OPTSTRING.
  447. X
  448. X   If an element of ARGV starts with '-', and is not exactly "-" or "--",
  449. X   then it is an option element.  The characters of this element
  450. X   (aside from the initial '-') are option characters.  If `getopt'
  451. X   is called repeatedly, it returns successively each of theoption characters
  452. X   from each of the option elements.
  453. X
  454. X   If `getopt' finds another option character, it returns that character,
  455. X   updating `optind' and `nextchar' so that the next call to `getopt' can
  456. X   resume the scan with the following option character or ARGV-element.
  457. X
  458. X   If there are no more option characters, `getopt' returns `EOF'.
  459. X   Then `optind' is the index in ARGV of the first ARGV-element
  460. X   that is not an option.  (The ARGV-elements have been permuted
  461. X   so that those that are not options now come last.)
  462. X
  463. X   OPTSTRING is a string containing the legitimate option characters.
  464. X   A colon in OPTSTRING means that the previous character is an option
  465. X   that wants an argument.  The argument is taken from the rest of the
  466. X   current ARGV-element, or from the following ARGV-element,
  467. X   and returned in `optarg'.
  468. X
  469. X   If an option character is seen that is not listed in OPTSTRING,
  470. X   return '?' after printing an error message.  If you set `opterr' to
  471. X   zero, the error message is suppressed but we still return '?'.
  472. X
  473. X   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
  474. X   so the following text in the same ARGV-element, or the text of the following
  475. X   ARGV-element, is returned in `optarg.  Two colons mean an option that
  476. X   wants an optional arg; if there is text in the current ARGV-element,
  477. X   it is returned in `optarg'.
  478. X
  479. X   If OPTSTRING starts with `-', it requests a different method of handling the
  480. X   non-option ARGV-elements.  See the comments about RETURN_IN_ORDER, above.  */
  481. X
  482. Xint
  483. Xgetopt (argc, argv, optstring)
  484. X     int argc;
  485. X     char **argv;
  486. X     char *optstring;
  487. X{
  488. X  /* Initialize the internal data when the first call is made.
  489. X     Start processing options with ARGV-element 1 (since ARGV-element 0
  490. X     is the program name); the sequence of previously skipped
  491. X     non-option ARGV-elements is empty.  */
  492. X
  493. X  if (optind == 0)
  494. X    {
  495. X      first_nonopt = last_nonopt = optind = 1;
  496. X
  497. X      nextchar = 0;
  498. X
  499. X      /* Determine how to handle the ordering of options and nonoptions.  */
  500. X
  501. X      if (optstring[0] == '-')
  502. X    ordering = RETURN_IN_ORDER;
  503. X      else if (getenv ("_POSIX_OPTION_ORDER") != 0)
  504. X    ordering = REQUIRE_ORDER;
  505. X      else
  506. X    ordering = PERMUTE;
  507. X    }
  508. X
  509. X  if (nextchar == 0 || *nextchar == 0)
  510. X    {
  511. X      if (ordering == PERMUTE)
  512. X    {
  513. X      /* If we have just processed some options following some non-options,
  514. X         exchange them so that the options come first.  */
  515. X
  516. X      if (first_nonopt != last_nonopt && last_nonopt != optind)
  517. X        exchange (argv);
  518. X      else if (last_nonopt != optind)
  519. X        first_nonopt = optind;
  520. X
  521. X      /* Now skip any additional non-options
  522. X         and extend the range of non-options previously skipped.  */
  523. X
  524. X      while (optind < argc
  525. X         && (argv[optind][0] != '-'
  526. X             || argv[optind][1] == 0))
  527. X        optind++;
  528. X      last_nonopt = optind;
  529. X    }
  530. X
  531. X      /* Special ARGV-element `--' means premature end of options.
  532. X     Skip it like a null option,
  533. X     then exchange with previous non-options as if it were an option,
  534. X     then skip everything else like a non-option.  */
  535. X
  536. X      if (optind != argc && !strcmp (argv[optind], "--"))
  537. X    {
  538. X      optind++;
  539. X
  540. X      if (first_nonopt != last_nonopt && last_nonopt != optind)
  541. X        exchange (argv);
  542. X      else if (first_nonopt == last_nonopt)
  543. X        first_nonopt = optind;
  544. X      last_nonopt = argc;
  545. X
  546. X      optind = argc;
  547. X    }
  548. X
  549. X      /* If we have done all the ARGV-elements, stop the scan
  550. X     and back over any non-options that we skipped and permuted.  */
  551. X
  552. X      if (optind == argc)
  553. X    {
  554. X      /* Set the next-arg-index to point at the non-options
  555. X         that we previously skipped, so the caller will digest them.  */
  556. X      if (first_nonopt != last_nonopt)
  557. X        optind = first_nonopt;
  558. X      return EOF;
  559. X    }
  560. X     
  561. X      /* If we have come to a non-option and did not permute it,
  562. X     either stop the scan or describe it to the caller and pass it by.  */
  563. X
  564. X      if (argv[optind][0] != '-' || argv[optind][1] == 0)
  565. X    {
  566. X      if (ordering == REQUIRE_ORDER)
  567. X        return EOF;
  568. X      optarg = argv[optind++];
  569. X      return 0;
  570. X    }
  571. X
  572. X      /* We have found another option-ARGV-element.
  573. X     Start decoding its characters.  */
  574. X
  575. X      nextchar = argv[optind] + 1;
  576. X    }
  577. X
  578. X  /* Look at and handle the next option-character.  */
  579. X
  580. X  {
  581. X    char c = *nextchar++;
  582. X    char *temp = (char *) index (optstring, c);
  583. X
  584. X    /* Increment `optind' when we start to process its last character.  */
  585. X    if (*nextchar == 0)
  586. X      optind++;
  587. X
  588. X    if (temp == 0 || c == ':')
  589. X      {
  590. X    if (opterr != 0)
  591. X      {
  592. X        if (c < 040 || c >= 0177)
  593. X          fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
  594. X               argv[0], c);
  595. X        else
  596. X          fprintf (stderr, "%s: unrecognized option `-%c'\n",
  597. X               argv[0], c);
  598. X      }
  599. X    return '?';
  600. X      }
  601. X    if (temp[1] == ':')
  602. X      {
  603. X    if (temp[2] == ':')
  604. X      {
  605. X        /* This is an option that accepts an argument optionally.  */
  606. X        if (*nextchar != 0)
  607. X          {
  608. X            optarg = nextchar;
  609. X        optind++;
  610. X          }
  611. X        else
  612. X          optarg = 0;
  613. X        nextchar = 0;
  614. X      }
  615. X    else
  616. X      {
  617. X        /* This is an option that requires an argument.  */
  618. X        if (*nextchar != 0)
  619. X          {
  620. X        optarg = nextchar;
  621. X        /* If we end this ARGV-element by taking the rest as an arg,
  622. X           we must advance to the next element now.  */
  623. X        optind++;
  624. X          }
  625. X        else if (optind == argc)
  626. X          {
  627. X        if (opterr != 0)
  628. X          fprintf (stderr, "%s: no argument for `-%c' option\n",
  629. X               argv[0], c);
  630. X        c = '?';
  631. X          }
  632. X        else
  633. X          /* We already incremented `optind' once;
  634. X         increment it again when taking next ARGV-elt as argument.  */
  635. X          optarg = argv[optind++];
  636. X        nextchar = 0;
  637. X      }
  638. X      }
  639. X    return c;
  640. X  }
  641. X}
  642. X
  643. X#ifdef TEST
  644. X
  645. X/* Compile with -DTEST to make an executable for use in testing
  646. X   the above definition of `getopt'.  */
  647. X
  648. Xint
  649. Xmain (argc, argv)
  650. X     int argc;
  651. X     char **argv;
  652. X{
  653. X  char c;
  654. X  int digit_optind = 0;
  655. X
  656. X  while (1)
  657. X    {
  658. X      int this_option_optind = optind;
  659. X      if ((c = getopt (argc, argv, "abc:d:0123456789")) == EOF)
  660. X    break;
  661. X
  662. X      switch (c)
  663. X    {
  664. X    case '0':
  665. X    case '1':
  666. X    case '2':
  667. X    case '3':
  668. X    case '4':
  669. X    case '5':
  670. X    case '6':
  671. X    case '7':
  672. X    case '8':
  673. X    case '9':
  674. X      if (digit_optind != 0 && digit_optind != this_option_optind)
  675. X        printf ("digits occur in two different argv-elements.\n");
  676. X      digit_optind = this_option_optind;
  677. X      printf ("option %c\n", c);
  678. X      break;
  679. X
  680. X    case 'a':
  681. X      printf ("option a\n");
  682. X      break;
  683. X
  684. X    case 'b':
  685. X      printf ("option b\n");
  686. X      break;
  687. X
  688. X    case 'c':
  689. X      printf ("option c with value `%s'\n", optarg);
  690. X      break;
  691. X
  692. X    case '?':
  693. X      break;
  694. X
  695. X    default:
  696. X      printf ("?? getopt returned character code 0%o ??\n", c);
  697. X    }
  698. X    }
  699. X
  700. X  if (optind < argc)
  701. X    {
  702. X      printf ("non-option ARGV-elements: ");
  703. X      while (optind < argc)
  704. X    printf ("%s ", argv[optind++]);
  705. X      printf ("\n");
  706. X    }
  707. X
  708. X  return 0;
  709. X}
  710. X
  711. X#endif /* TEST */
  712. END_OF_FILE
  713. if test 12436 -ne `wc -c <'cperf/src/getopt.c'`; then
  714.     echo shar: \"'cperf/src/getopt.c'\" unpacked with wrong size!
  715. fi
  716. # end of 'cperf/src/getopt.c'
  717. fi
  718. if test -f 'cperf/src/hashtable.c' -a "${1}" != "-c" ; then 
  719.   echo shar: Will not clobber existing file \"'cperf/src/hashtable.c'\"
  720. else
  721. echo shar: Extracting \"'cperf/src/hashtable.c'\" \(3281 characters\)
  722. sed "s/^X//" >'cperf/src/hashtable.c' <<'END_OF_FILE'
  723. X/* Hash table for checking keyword links.  Implemented using double hashing.
  724. X   Copyright (C) 1989 Free Software Foundation, Inc.
  725. X   written by Douglas C. Schmidt (schmidt@ics.uci.edu)
  726. X
  727. XThis file is part of GNU GPERF.
  728. X
  729. XGNU GPERF is free software; you can redistribute it and/or modify
  730. Xit under the terms of the GNU General Public License as published by
  731. Xthe Free Software Foundation; either version 1, or (at your option)
  732. Xany later version.
  733. X
  734. XGNU GPERF is distributed in the hope that it will be useful,
  735. Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
  736. XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  737. XGNU General Public License for more details.
  738. X
  739. XYou should have received a copy of the GNU General Public License
  740. Xalong with GNU GPERF; see the file COPYING.  If not, write to
  741. Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  742. X
  743. X#include <stdio.h>
  744. X#include "hashtable.h"
  745. X#include "options.h"
  746. X
  747. X/* Locally visible hash table. */
  748. Xstatic HASH_TABLE hash_table;
  749. X
  750. X#define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X)))
  751. X
  752. Xstatic unsigned
  753. Xhash_pjw (str)
  754. X     char *str;
  755. X{
  756. X  char    *temp;
  757. X  unsigned g, h = 0;
  758. X   
  759. X  for (temp = str; *temp; temp++) 
  760. X    {
  761. X      h = (h << 4) + (*temp * 13);
  762. X      if (g = h & 0xf0000000) 
  763. X        {
  764. X          h ^= (g >> 24);
  765. X          h ^= g;
  766. X        }
  767. X    }
  768. X
  769. X  return h;
  770. X}
  771. X
  772. X/* The size of the hash table is always the smallest power of 2 >= the size
  773. X   indicated by the user.  this allows several optimizations, including
  774. X   the use of double hashing and elimination of the mod instruction.
  775. X   note that the size had better be larger than the number of items
  776. X   in the hash table, else there's trouble!!! */
  777. X
  778. Xvoid
  779. Xhash_table_init (s)
  780. X     int s;
  781. X{
  782. X    char *xmalloc ();
  783. X  hash_table.size  = POW (s);
  784. X  hash_table.table = (LIST_NODE **) xmalloc (hash_table.size * sizeof (*hash_table.table));
  785. X  bzero ((char *) hash_table.table, hash_table.size * sizeof *hash_table.table);
  786. X}
  787. X
  788. X/* Frees the dynamically allocated table. */
  789. X
  790. Xvoid
  791. Xhash_table_destroy ()
  792. X{ 
  793. X  if (OPTION_ENABLED (option, DEBUG))
  794. X    {
  795. X      int i;
  796. X
  797. X      fprintf (stderr, "\ndumping the hash table\n");
  798. X    
  799. X      for (i = hash_table.size - 1; i >= 0; i--)
  800. X        if (hash_table.table[i])
  801. X          fprintf (stderr, "location[%d] = key set %s, key %s\n",
  802. X                   i, hash_table.table[i]->key_set, hash_table.table[i]->key);
  803. X
  804. X      fprintf (stderr, "end dumping hash table\n\n");
  805. X    }
  806. X}
  807. X
  808. X/* If the ITEM is already in the hash table return the item found
  809. X   in the table.  Otherwise inserts the ITEM, and returns FALSE.
  810. X   Uses double hashing. */
  811. X
  812. XLIST_NODE *
  813. Xretrieve (item, ignore_length)
  814. X     LIST_NODE *item;
  815. X     int        ignore_length;
  816. X{
  817. X  unsigned hash_val  = hash_pjw (item->key_set);
  818. X  int      probe     = hash_val & hash_table.size - 1;
  819. X  int      increment = (hash_val ^ item->length | 1) & hash_table.size - 1;
  820. X  
  821. X  while (hash_table.table[probe]
  822. X         && (strcmp (hash_table.table[probe]->key_set, item->key_set)
  823. X             || (!ignore_length && hash_table.table[probe]->length != item->length)))
  824. X    probe = probe + increment & hash_table.size - 1;
  825. X  
  826. X  if (hash_table.table[probe])
  827. X    return hash_table.table[probe];
  828. X  else
  829. X    {
  830. X      hash_table.table[probe] = item;
  831. X      return 0;
  832. X    }
  833. X}
  834. X
  835. X
  836. END_OF_FILE
  837. if test 3281 -ne `wc -c <'cperf/src/hashtable.c'`; then
  838.     echo shar: \"'cperf/src/hashtable.c'\" unpacked with wrong size!
  839. fi
  840. # end of 'cperf/src/hashtable.c'
  841. fi
  842. if test -f 'cperf/src/listnode.c' -a "${1}" != "-c" ; then 
  843.   echo shar: Will not clobber existing file \"'cperf/src/listnode.c'\"
  844. else
  845. echo shar: Extracting \"'cperf/src/listnode.c'\" \(4294 characters\)
  846. sed "s/^X//" >'cperf/src/listnode.c' <<'END_OF_FILE'
  847. X/* Creates and initializes a new list node.
  848. X   Copyright (C) 1989 Free Software Foundation, Inc.
  849. X   written by Douglas C. Schmidt (schmidt@ics.uci.edu)
  850. X
  851. XThis file is part of GNU GPERF.
  852. X
  853. XGNU GPERF is free software; you can redistribute it and/or modify
  854. Xit under the terms of the GNU General Public License as published by
  855. Xthe Free Software Foundation; either version 1, or (at your option)
  856. Xany later version.
  857. X
  858. XGNU GPERF is distributed in the hope that it will be useful,
  859. Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
  860. XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  861. XGNU General Public License for more details.
  862. X
  863. XYou should have received a copy of the GNU General Public License
  864. Xalong with GNU GPERF; see the file COPYING.  If not, write to
  865. Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  866. X
  867. X#include <stdio.h>
  868. X#include "options.h"
  869. X#include "listnode.h"
  870. X#include "stderr.h"
  871. X
  872. X/* See comments in perfect.cc. */
  873. Xextern int occurrences[ALPHABET_SIZE]; 
  874. X
  875. X/* Sorts the key set alphabetically to speed up subsequent operations.
  876. X   Uses insertion sort since the set is probably quite small. */
  877. X
  878. Xstatic void 
  879. Xset_sort (base, len)
  880. X     char *base;
  881. X     int len;
  882. X{
  883. X  int i, j;
  884. X
  885. X  for (i = 0, j = len - 1; i < j; i++)
  886. X    {
  887. X      char curr, tmp;
  888. X      
  889. X      for (curr = i + 1, tmp = base[curr]; curr > 0 && tmp < base[curr-1]; curr--)
  890. X        base[curr] = base[curr - 1];
  891. X
  892. X      base[curr] = tmp;
  893. X
  894. X    }
  895. X}
  896. X
  897. X/* Initializes a List_Node.  This requires obtaining memory for the KEY_SET
  898. X   and UNIQ_SET, initializing them using the information stored in the
  899. X   KEY_POSITIONS array in Options, and checking for simple errors.
  900. X   It's important to note that KEY and REST are both pointers to
  901. X   the different offsets into the same block of dynamic memory pointed to
  902. X   by parameter K. The data member REST is used to store any additional fields 
  903. X   of the input file (it is set to the "" string if Option[TYPE] is not enabled).
  904. X   This is useful if the user wishes to incorporate a lookup structure,
  905. X   rather than just an array of keys. */
  906. X
  907. XLIST_NODE *
  908. Xmake_list_node (k, len)
  909. X     char *k;
  910. X     int len;
  911. X{
  912. X    char *xmalloc ();
  913. X  LIST_NODE *temp = (LIST_NODE *) xmalloc (sizeof (LIST_NODE));
  914. X  int positions  = 1 + (OPTION_ENABLED (option, ALLCHARS) ? len : TOTAL_POSITIONS (option) + 1);
  915. X  char *ptr, *ptr1, *ptr2;
  916. X
  917. X  temp->key_set  = (char *) xmalloc (positions + positions); /* Save 1 call to new. */
  918. X  temp->uniq_set = temp->key_set + positions;
  919. X  ptr            = temp->key_set;
  920. X  k[len]         = '\0';        /* Null terminate KEY to separate it from REST. */
  921. X  temp->key      = k;
  922. X  temp->next     = 0;
  923. X  temp->index    = 0;
  924. X  temp->length   = len;
  925. X  temp->link     = 0;
  926. X  temp->rest     = OPTION_ENABLED (option, TYPE) ? k + len + 1 : "";
  927. X
  928. X  if (OPTION_ENABLED (option, ALLCHARS)) /* Use all the character position in the KEY. */
  929. X
  930. X    for (; *k; k++, ptr++)
  931. X      ++occurrences[*ptr = *k];
  932. X
  933. X  else                          /* Only use those character positions specified by the user. */
  934. X    {                           
  935. X      int i;
  936. X
  937. X      /* Iterate thru the list of key_positions, initializing occurrences table
  938. X         and temp->key_set (via char * pointer ptr). */
  939. X
  940. X      for(RESET (option); (i = GET (option)) != EOS; )
  941. X        {
  942. X          if (i == WORD_END)    /* Special notation for last KEY position, i.e. '$'. */
  943. X            *ptr = temp->key[len - 1];
  944. X          else if (i <= len)    /* Within range of KEY length, so we'll keep it. */
  945. X            *ptr = temp->key[i - 1];
  946. X          else                  /* Out of range of KEY length, so we'll just skip it. */
  947. X            continue;
  948. X          ++occurrences[*ptr++];
  949. X        }
  950. X
  951. X      if (ptr == temp->key_set) /* Didn't get any hits, i.e., no usable positions. */
  952. X        report_error ("can't hash keyword %s with chosen key positions\n%a", temp->key);
  953. X    }
  954. X
  955. X  *ptr = '\0';                  /* Terminate this bastard.... */
  956. X  set_sort (temp->key_set, ptr - temp->key_set); /* Sort the KEY_SET items alphabetically. */
  957. X
  958. X  /* Eliminate UNIQ_SET duplicates, this saves time later on.... */
  959. X
  960. X  for (ptr1 = temp->key_set, ptr2 = temp->uniq_set; *ptr1; ptr1++)
  961. X    if (*ptr1 != ptr1[1])
  962. X      *ptr2++ = *ptr1;
  963. X
  964. X  *ptr2 = '\0';                 /* NULL terminate the UNIQ_SET. */
  965. X  return temp;
  966. X}
  967. END_OF_FILE
  968. if test 4294 -ne `wc -c <'cperf/src/listnode.c'`; then
  969.     echo shar: \"'cperf/src/listnode.c'\" unpacked with wrong size!
  970. fi
  971. # end of 'cperf/src/listnode.c'
  972. fi
  973. if test -f 'cperf/src/options.h' -a "${1}" != "-c" ; then 
  974.   echo shar: Will not clobber existing file \"'cperf/src/options.h'\"
  975. else
  976. echo shar: Extracting \"'cperf/src/options.h'\" \(5762 characters\)
  977. sed "s/^X//" >'cperf/src/options.h' <<'END_OF_FILE'
  978. X/* Handles parsing the Options provided to the user.
  979. X
  980. X   Copyright (C) 1989 Free Software Foundation, Inc.
  981. X   written by Douglas C. Schmidt (schmidt@ics.uci.edu)
  982. X
  983. XThis file is part of GNU GPERF.
  984. X
  985. XGNU GPERF is free software; you can redistribute it and/or modify
  986. Xit under the terms of the GNU General Public License as published by
  987. Xthe Free Software Foundation; either version 1, or (at your option)
  988. Xany later version.
  989. X
  990. XGNU GPERF is distributed in the hope that it will be useful,
  991. Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
  992. XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  993. XGNU General Public License for more details.
  994. X
  995. XYou should have received a copy of the GNU General Public License
  996. Xalong with GNU GPERF; see the file COPYING.  If not, write to
  997. Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  998. X
  999. X/* This module provides a uniform interface to the various Options available
  1000. X   to a user of the Perfect.hash function generator.  In addition to the
  1001. X   run-time Options, found in the Option_Type below, there is also the
  1002. X   hash table Size and the Keys to be used in the hashing.
  1003. X   The overall design of this module was an experiment in using C++
  1004. X   classes as a mechanism to enhance centralization of option and
  1005. X   and error handling, which tend to get out of hand in a C program. */
  1006. X
  1007. X#ifndef _options_h
  1008. X#define _options_h
  1009. X
  1010. X#include <stdio.h>
  1011. X#include "prototype.h"
  1012. X
  1013. X/* Enumerate the potential debugging Options. */
  1014. X
  1015. Xenum option_type 
  1016. X{
  1017. X  DEBUG        = 01,            /* Enable debugging (prints diagnostics to Std_Err). */
  1018. X  ORDER        = 02,            /* Apply ordering heuristic to speed-up search time. */
  1019. X  ANSI         = 04,            /* Generate ANSI prototypes. */
  1020. X  ALLCHARS     = 010,           /* Use all characters in hash function. */
  1021. X  GNU          = 020,           /* Assume GNU extensions (primarily function inline). */
  1022. X  TYPE         = 040,           /* Handle user-defined type structured keyword input. */
  1023. X  RANDOM       = 0100,          /* Randomly initialize the associated values table. */
  1024. X  DEFAULTCHARS = 0200,          /* Make default char positions be 1,$ (end of keyword). */
  1025. X  SWITCH       = 0400,          /* Generate switch output to save space. */
  1026. X  POINTER      = 01000,         /* Have in_word_set function return pointer, not boolean. */
  1027. X  NOLENGTH     = 02000,         /* Don't include keyword length in hash computations. */
  1028. X  LENTABLE     = 04000,         /* Generate a length table for string comparison. */
  1029. X  DUP          = 010000,        /* Handle duplicate hash values for keywords. */
  1030. X  FAST         = 020000,        /* Generate the hash function ``fast.'' */
  1031. X  NOTYPE       = 040000,    /* Don't include user-defined type definition
  1032. X                 * in output -- it's already defined elsewhere. */
  1033. X  COMP         = 0100000,       /* Generate strncmp rather than strcmp. */
  1034. X  GLOBAL       = 0200000,       /* Make the keyword table a global variable. */
  1035. X  CONST        = 0400000,       /* Make the generated tables readonly (const). */
  1036. X};
  1037. X
  1038. X/* Define some useful constants. */
  1039. X
  1040. X/* Max size of each word's key set. */
  1041. X#define MAX_KEY_POS (128 - 1)
  1042. X
  1043. X/* Signals the start of a word. */
  1044. X#define WORD_START 1           
  1045. X
  1046. X/* Signals the end of a word. */
  1047. X#define WORD_END 0             
  1048. X
  1049. X/* Signals end of the key list. */
  1050. X#define EOS MAX_KEY_POS        
  1051. X
  1052. X/* Returns TRUE if option O is enabled. */
  1053. X#define OPTION_ENABLED(OW,O) (OW.option_word & (int)O)
  1054. X
  1055. X/* Enables option O in OPTION_WORD. */
  1056. X#define SET_OPTION(OW,O) (OW.option_word |= (int)O)
  1057. X
  1058. X/* Disable option O in OPTION_WORD. */
  1059. X#define UNSET_OPTION(OW,O) (OW.option_word &= ~(int)(O))
  1060. X
  1061. X/* Returns total distinct key positions. */
  1062. X#define TOTAL_POSITIONS(O) (O.total_key_positions)
  1063. X
  1064. X/* Initializes the key Iterator. */
  1065. X#define RESET(O) (O.key_pos = 0)
  1066. X
  1067. X/* Returns current key_position and advances index. */
  1068. X#define GET(O) (O.key_positions[O.key_pos++])
  1069. X
  1070. X/* Sets the size of the table size. */
  1071. X#define SET_ASSO_MAX(O,R) (O.size = (R))
  1072. X
  1073. X/* Returns the size of the table size. */
  1074. X#define GET_ASSO_MAX(O) (O.size)
  1075. X
  1076. X/* Returns the jump value. */
  1077. X#define GET_JUMP(O) (O.jump)
  1078. X
  1079. X/* Returns the iteration value. */
  1080. X#define GET_ITERATIONS(O) (O.iterations)
  1081. X
  1082. X/* Returns the lookup function name. */
  1083. X#define GET_FUNCTION_NAME(O) (O.function_name)
  1084. X
  1085. X/* Returns the keyword key name. */
  1086. X#define GET_KEY_NAME(O) (O.key_name)
  1087. X
  1088. X/* Returns the hash function name. */
  1089. X#define GET_HASH_NAME(O) (O.hash_name)
  1090. X
  1091. X/* Returns the initial associated character value. */
  1092. X#define INITIAL_VALUE(O) (O.initial_asso_value)
  1093. X
  1094. X/* Class manager for gperf program options. */
  1095. X
  1096. Xtypedef struct options
  1097. X{
  1098. X  int    option_word;           /* Holds the user-specified Options. */
  1099. X  int    total_key_positions;   /* Total number of distinct key_positions. */
  1100. X  int    size;                  /* Range of the hash table. */
  1101. X  int    key_pos;               /* Tracks current key position for Iterator. */
  1102. X  int    jump;                  /* Jump length when trying alternative values. */
  1103. X  int    initial_asso_value;    /* Initial value for asso_values table. */
  1104. X  int    argument_count;        /* Records count of command-line arguments. */
  1105. X  int    iterations;            /* Amount to iterate when a collision occurs. */
  1106. X  char **argument_vector;       /* Stores a pointer to command-line vector. */
  1107. X  char  *function_name;         /* Name used for generated lookup function. */
  1108. X  char  *key_name;              /* Name used for keyword key. */
  1109. X  char  *hash_name;             /* Name used for generated hash function. */
  1110. X  char   key_positions[MAX_KEY_POS]; /* Contains user-specified key choices. */
  1111. X} OPTIONS;
  1112. X
  1113. Xextern void    options_init P ((int argc, char *argv[]));
  1114. Xextern void    options_destroy P ((void));
  1115. Xextern OPTIONS option;       
  1116. X#endif /* _options_h */
  1117. END_OF_FILE
  1118. if test 5762 -ne `wc -c <'cperf/src/options.h'`; then
  1119.     echo shar: \"'cperf/src/options.h'\" unpacked with wrong size!
  1120. fi
  1121. # end of 'cperf/src/options.h'
  1122. fi
  1123. if test -f 'cperf/src/perfect.c' -a "${1}" != "-c" ; then 
  1124.   echo shar: Will not clobber existing file \"'cperf/src/perfect.c'\"
  1125. else
  1126. echo shar: Extracting \"'cperf/src/perfect.c'\" \(9830 characters\)
  1127. sed "s/^X//" >'cperf/src/perfect.c' <<'END_OF_FILE'
  1128. X/* Provides high-level routines to manipulate the keywork list 
  1129. X   structures the code generation output.
  1130. X   Copyright (C) 1989 Free Software Foundation, Inc.
  1131. X   written by Douglas C. Schmidt (schmidt@ics.uci.edu)
  1132. X
  1133. XThis file is part of GNU GPERF.
  1134. X
  1135. XGNU GPERF is free software; you can redistribute it and/or modify
  1136. Xit under the terms of the GNU General Public License as published by
  1137. Xthe Free Software Foundation; either version 1, or (at your option)
  1138. Xany later version.
  1139. X
  1140. XGNU GPERF is distributed in the hope that it will be useful,
  1141. Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
  1142. XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1143. XGNU General Public License for more details.
  1144. X
  1145. XYou should have received a copy of the GNU General Public License
  1146. Xalong with GNU GPERF; see the file COPYING.  If not, write to
  1147. Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  1148. X
  1149. X#include <stdio.h>
  1150. X#include <assert.h>
  1151. X#include <ctype.h>
  1152. X#include "options.h"
  1153. X#include "perfect.h"
  1154. X#include "stderr.h"
  1155. X
  1156. Xint occurrences[ALPHABET_SIZE]; /* Counts occurrences of each key set character. */
  1157. Xint asso_values[ALPHABET_SIZE]; /* Value associated with each character. */
  1158. X
  1159. X/* Locally visible PERFECT object. */
  1160. X
  1161. XPERFECT perfect;
  1162. X
  1163. X/* Efficiently returns the least power of two greater than or equal to X! */
  1164. X#define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X)))
  1165. X
  1166. X/* Reads input keys, possibly applies the reordering heuristic, sets the
  1167. X   maximum associated value size (rounded up to the nearest power of 2),
  1168. X   may initialize the associated values array, and determines the maximum
  1169. X   hash table size.  Note: using the random numbers is often helpful,
  1170. X   though not as deterministic, of course! */
  1171. X
  1172. Xvoid
  1173. Xperfect_init ()
  1174. X{
  1175. X  int asso_value_max;
  1176. X  int len;
  1177. X
  1178. X  perfect.best_char_choice = 0;
  1179. X  perfect.best_asso_value = 0;
  1180. X  read_keys ();
  1181. X  if (OPTION_ENABLED (option, ORDER))
  1182. X    reorder ();
  1183. X
  1184. X  asso_value_max = GET_ASSO_MAX (option);
  1185. X  len            = length ();
  1186. X  
  1187. X  asso_value_max = (asso_value_max ? asso_value_max * len : len);
  1188. X  SET_ASSO_MAX (option, POW (asso_value_max));
  1189. X  
  1190. X  if (OPTION_ENABLED (option, RANDOM))
  1191. X    {
  1192. X      int i;
  1193. X
  1194. X      srandom (time (0));
  1195. X      
  1196. X      for (i = 0; i < ALPHABET_SIZE; i++)
  1197. X        asso_values[i] = (random () & asso_value_max - 1);
  1198. X      
  1199. X    }
  1200. X  else
  1201. X    {
  1202. X      int asso_value = INITIAL_VALUE (option);
  1203. X      
  1204. X      if (asso_value)           /* Initialize array if user requests non-zero default. */
  1205. X        {
  1206. X          int i;
  1207. X
  1208. X          for (i = ALPHABET_SIZE - 1; i >= 0; i--)
  1209. X            asso_values[i] = asso_value & GET_ASSO_MAX (option) - 1;
  1210. X
  1211. X        }
  1212. X    }
  1213. X  perfect.max_hash_value = max_key_length () + GET_ASSO_MAX (option) * 
  1214. X    (OPTION_ENABLED (option, ALLCHARS) ? max_key_length () : TOTAL_POSITIONS (option));
  1215. X  
  1216. X  if (OPTION_ENABLED (option, DEBUG))
  1217. X    fprintf (stderr, "number of keys = %d\nmaximum associated value is %d\
  1218. X\nmaximum size of hash table is %d\n", len, asso_value_max, perfect.max_hash_value);
  1219. X}
  1220. X
  1221. X/* Merge two disjoint hash key sets to form the ordered union of the sets.
  1222. X   Precondition: both set_1 and set_2 must be ordered. Returns the length
  1223. X   of the combined set. */
  1224. X
  1225. Xstatic int 
  1226. Xmerge_sets (set_1, set_2, set_3)
  1227. X     char *set_1;
  1228. X     char *set_2;
  1229. X     char *set_3;
  1230. X{
  1231. X  char *base = set_3;
  1232. X  
  1233. X  while (*set_1 && *set_2)
  1234. X    if (*set_1 == *set_2)
  1235. X      *set_3++ = *set_1++, set_2++; 
  1236. X    else
  1237. X      *set_3++ = *set_1 < *set_2 ? *set_1++ : *set_2++;
  1238. X  
  1239. X  while (*set_1)
  1240. X    *set_3++ = *set_1++; 
  1241. X  
  1242. X  while (*set_2)
  1243. X    *set_3++ = *set_2++; 
  1244. X  
  1245. X  *set_3 = '\0';
  1246. X  return set_3 - base;
  1247. X}
  1248. X
  1249. X/* Sort the UNION_SET in increasing frequency of occurrence.
  1250. X   This speeds up later processing since we may assume the resulting
  1251. X   set (Set_3, in this case), is ordered. Uses insertion sort, since
  1252. X   the UNION_SET is typically short. */
  1253. X  
  1254. Xstatic void 
  1255. Xsort_set (union_set, len)
  1256. X     char *union_set;
  1257. X     int   len;
  1258. X{
  1259. X  int i, j;
  1260. X  
  1261. X  for (i = 0, j = len - 1; i < j; i++)
  1262. X    {
  1263. X      char curr, tmp;
  1264. X
  1265. X      for (curr = i+1, tmp = union_set[curr]; 
  1266. X           curr>0 && occurrences[tmp] < occurrences[union_set[curr-1]]; 
  1267. X           curr--)
  1268. X        union_set[curr] = union_set[curr - 1];
  1269. X      
  1270. X      union_set[curr] = tmp;
  1271. X    }
  1272. X}
  1273. X
  1274. X/* Generate a key set's hash value. */
  1275. X
  1276. Xstatic int 
  1277. Xhash (key_node)
  1278. X     LIST_NODE *key_node;
  1279. X{                             
  1280. X  int   sum = OPTION_ENABLED (option, NOLENGTH) ? 0 : key_node->length;
  1281. X  char *ptr;
  1282. X
  1283. X  for (ptr = key_node->key_set; *ptr; ptr++)
  1284. X      sum += asso_values[*ptr];
  1285. X  
  1286. X  return key_node->hash_value = sum;
  1287. X}
  1288. X
  1289. X/* Find out how character value change affects successfully hashed items.
  1290. X   Returns FALSE if no other hash values are affected, else returns TRUE.
  1291. X   Note that because Option.Get_Asso_Max is a power of two we can guarantee
  1292. X   that all legal Asso_Values are visited without repetition since
  1293. X   Option.Get_Jump was forced to be an odd value! */
  1294. X
  1295. Xstatic bool 
  1296. Xaffects_prev (c, curr)
  1297. X     char c;
  1298. X     LIST_NODE *curr;
  1299. X{
  1300. X  int original_char = asso_values[c];
  1301. X  int i = !OPTION_ENABLED (option, FAST) ? GET_ASSO_MAX (option) :
  1302. X    GET_ITERATIONS (option) == 0 ? key_list.list_len : GET_ITERATIONS (option);
  1303. X
  1304. X  /* Try all legal asso_values. */
  1305. X
  1306. X  while (--i >= 0)
  1307. X    { 
  1308. X      int        number_of_hits = 0;
  1309. X      LIST_NODE *ptr;
  1310. X
  1311. X      asso_values[c] = asso_values[c] + (OPTION_ENABLED (option, FAST) ? random () : GET_JUMP (option))
  1312. X        & GET_ASSO_MAX (option) - 1;
  1313. X      bool_array_reset ();       /* Ullman's array is a win, O(1) intialization time! */
  1314. X      
  1315. X      for (ptr = key_list.head; ; ptr = ptr->next)
  1316. X        {
  1317. X          if (lookup (hash (ptr)) && ++number_of_hits >= perfect.fewest_hits)
  1318. X            goto bottom_of_main_loop;
  1319. X          if (ptr == curr)
  1320. X            break;
  1321. X        }    
  1322. X      
  1323. X      perfect.best_asso_value  = asso_values[perfect.best_char_choice = c];
  1324. X      if ((perfect.fewest_hits = number_of_hits) == 0) /* Use if 0 hits for this value. */
  1325. X        return FALSE;        
  1326. X      
  1327. X    bottom_of_main_loop: ;
  1328. X    }
  1329. X  
  1330. X  asso_values[c] = original_char; /* Restore original values, no more tries. */
  1331. X  return TRUE; /* If we're this far it's time to try the next character.... */
  1332. X}
  1333. X
  1334. X#ifdef sparc
  1335. X#include <alloca.h>
  1336. X#endif
  1337. X
  1338. X/* Change a character value, try least-used characters first. */
  1339. X
  1340. Xstatic void 
  1341. Xchange (prior, curr)
  1342. X     LIST_NODE *prior;
  1343. X     LIST_NODE *curr;
  1344. X{
  1345. X  char      *union_set = (char *) alloca (2 * TOTAL_POSITIONS (option) + 1);
  1346. X  int        i = 1;
  1347. X  char      *temp;
  1348. X  LIST_NODE *ptr;
  1349. X
  1350. X  if (OPTION_ENABLED (option, DEBUG))        /* Very useful for debugging. */
  1351. X    fprintf (stderr, "collision, prior->key = %s, curr->key = %s, hash_value = %d\n",
  1352. X             prior->key, curr->key, curr->hash_value);
  1353. X  sort_set (union_set, merge_sets (prior->uniq_set, curr->uniq_set, union_set));
  1354. X  
  1355. X  /* Try changing some values, if change doesn't alter other values continue normal action. */
  1356. X  
  1357. X  perfect.fewest_hits = length ();
  1358. X  
  1359. X  for (temp = union_set; *temp; temp++)
  1360. X    if (!affects_prev (*temp, curr))
  1361. X      return; /* Good, doesn't affect previous hash values, we'll take it. */
  1362. X  
  1363. X  asso_values[perfect.best_char_choice] = perfect.best_asso_value; /* If none work take best value. */
  1364. X  
  1365. X  for (ptr = key_list.head; ; ptr = ptr->next, i++)
  1366. X    {
  1367. X      hash (ptr);
  1368. X      if (ptr == curr)
  1369. X        break;
  1370. X    }           
  1371. X  
  1372. X  if (OPTION_ENABLED (option, DEBUG))
  1373. X    fprintf (stderr, "changes on %d hash values still produce duplicates, continuing...\n", i);
  1374. X}
  1375. X
  1376. X/* Does the hard stuff....
  1377. X   Initializes the Ullman_Array, and then attempts to find a Perfect
  1378. X   function that will hash all the key words without getting any
  1379. X   duplications.  This is made much easier since we aren't attempting
  1380. X   to generate *minimum* functions, only Perfect ones.
  1381. X   If we can't generate a Perfect function in one pass *and* the user
  1382. X   hasn't enabled the DUP option, we'll inform the user to try the
  1383. X   randomization option, use -D, or choose alternative key positions.  
  1384. X   The alternatives (e.g., back-tracking) are too time-consuming, i.e,
  1385. X   exponential in the number of keys. */
  1386. X
  1387. Xint
  1388. Xperfect_generate ()
  1389. X{
  1390. X  LIST_NODE *curr;
  1391. X  bool_array_init (perfect.max_hash_value);
  1392. X  hash (key_list.head);
  1393. X  
  1394. X  for (curr = key_list.head->next; curr; curr = curr->next)
  1395. X    {
  1396. X      LIST_NODE *ptr;
  1397. X      hash (curr);
  1398. X      
  1399. X      for (ptr = key_list.head; ptr != curr; ptr = ptr->next)
  1400. X        if (ptr->hash_value == curr->hash_value)
  1401. X          {
  1402. X            change (ptr, curr);
  1403. X            break;
  1404. X          }
  1405. X    } 
  1406. X  
  1407. X  /* Make one final check, just to make sure nothing weird happened.... */
  1408. X  
  1409. X  for (bool_array_reset (), curr = key_list.head; curr; curr = curr->next)
  1410. X    if (lookup (hash (curr)))
  1411. X      if (OPTION_ENABLED (option, DUP)) /* We'll try to deal with this later..... */
  1412. X        break;
  1413. X      else /* Yow, big problems.  we're outta here! */
  1414. X        { 
  1415. X          report_error ("\nInternal error, duplicate value %d:\ntry options -D or -r, or use new key positions.\n\n", 
  1416. X                        hash (curr));
  1417. X          return 1;
  1418. X        }
  1419. X
  1420. X  /* First sorts the key word list by hash value, and the outputs the
  1421. X     list to the proper ostream. The generated hash table code is only 
  1422. X     output if the early stage of processing turned out O.K. */
  1423. X
  1424. X  sort ();
  1425. X  print_output ();
  1426. X  return 0;
  1427. X}
  1428. X
  1429. X/* Prints out some diagnostics upon completion. */
  1430. X
  1431. Xvoid 
  1432. Xperfect_destroy ()
  1433. X{                             
  1434. X  if (OPTION_ENABLED (option, DEBUG))
  1435. X    {
  1436. X      int i;
  1437. X
  1438. X      fprintf (stderr, "\ndumping occurrence and associated values tables\n");
  1439. X      
  1440. X      for (i = 0; i < ALPHABET_SIZE; i++)
  1441. X        if (occurrences[i])
  1442. X          fprintf (stderr, "asso_values[%c] = %3d, occurrences[%c] = %3d\n",
  1443. X                   i, asso_values[i], i, occurrences[i]);
  1444. X      
  1445. X      fprintf (stderr, "end table dumping\n");
  1446. X      
  1447. X    }
  1448. X}
  1449. X
  1450. END_OF_FILE
  1451. if test 9830 -ne `wc -c <'cperf/src/perfect.c'`; then
  1452.     echo shar: \"'cperf/src/perfect.c'\" unpacked with wrong size!
  1453. fi
  1454. # end of 'cperf/src/perfect.c'
  1455. fi
  1456. echo shar: End of archive 2 \(of 5\).
  1457. cp /dev/null ark2isdone
  1458. MISSING=""
  1459. for I in 1 2 3 4 5 ; do
  1460.     if test ! -f ark${I}isdone ; then
  1461.     MISSING="${MISSING} ${I}"
  1462.     fi
  1463. done
  1464. if test "${MISSING}" = "" ; then
  1465.     echo You have unpacked all 5 archives.
  1466.     rm -f ark[1-9]isdone
  1467. else
  1468.     echo You still need to unpack the following archives:
  1469.     echo "        " ${MISSING}
  1470. fi
  1471. ##  End of shell archive.
  1472. exit 0
  1473.  
  1474.