summaryrefslogtreecommitdiff
path: root/agen5/expGperf.c
diff options
context:
space:
mode:
Diffstat (limited to 'agen5/expGperf.c')
-rw-r--r--agen5/expGperf.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/agen5/expGperf.c b/agen5/expGperf.c
new file mode 100644
index 0000000..902f18b
--- /dev/null
+++ b/agen5/expGperf.c
@@ -0,0 +1,156 @@
+/**
+ * @file expGperf.c
+ *
+ * Time-stamp: "2012-01-15 08:38:23 bkorb"
+ *
+ * Create a perfect hash function program and use it to compute
+ * index values for a list of provided names. It also documents how
+ * to incorporate that hashing function into a generated C program.
+ *
+ * This file is part of AutoGen.
+ * Copyright (c) 1992-2012 Bruce Korb - all rights reserved
+ *
+ * AutoGen 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AutoGen 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SHELL_ENABLED
+HIDE_FN(SCM ag_scm_make_gperf(SCM name, SCM hlist))
+{
+ return SCM_UNDEFINED;
+}
+
+HIDE_FN(SCM ag_scm_gperf(SCM name, SCM str))
+{
+ return SCM_UNDEFINED;
+}
+#else
+
+/*=gfunc make_gperf
+ *
+ * what: build a perfect hash function program
+ * general_use:
+ *
+ * exparg: name , name of hash list
+ * exparg: strings , list of strings to hash ,, list
+ *
+ * doc: Build a program to perform perfect hashes of a known list of input
+ * strings. This function produces no output, but prepares a program
+ * named, @file{gperf_<name>} for use by the gperf function
+ * @xref{SCM gperf}.
+ *
+ * This program will be obliterated as AutoGen exits.
+ * However, you may incorporate the generated hashing function
+ * into your C program with commands something like the following:
+ *
+ * @example
+ * [+ (shellf "sed '/^int main(/,$d;/^#line/d' $@{gpdir@}/%s.c"
+ * name ) +]
+ * @end example
+ *
+ * where @code{name} matches the name provided to this @code{make-perf}
+ * function. @code{gpdir} is the variable used to store the name of the
+ * temporary directory used to stash all the files.
+=*/
+SCM
+ag_scm_make_gperf(SCM name, SCM hlist)
+{
+ static bool do_cleanup = true;
+
+ char const * pzName = ag_scm2zchars(name, "gperf name");
+ char const * pzList;
+ SCM newline = AG_SCM_STR2SCM(NEWLINE, (size_t)1);
+
+ if (! AG_SCM_STRING_P(name))
+ return SCM_UNDEFINED;
+
+ /*
+ * Construct the newline separated list of values
+ */
+ hlist = ag_scm_join(newline, hlist);
+ pzList = ag_scm2zchars(hlist, "hash list");
+
+ /*
+ * Stash the concatenated list somewhere, hopefully without an alloc.
+ */
+ {
+ char * cmd = aprf(MK_GPERF_SCRIPT, zMakeProg, pzName, pzList);
+
+ /*
+ * Run the command and ignore the results.
+ * In theory, the program should be ready.
+ */
+ pzList = shell_cmd(cmd);
+ AGFREE(cmd);
+
+ if (pzList != NULL)
+ free((void *)pzList);
+ }
+
+ if (do_cleanup) {
+ SCM_EVAL_CONST(MAKE_GPERF_CLEANUP);
+ do_cleanup = false;
+ }
+
+ return SCM_BOOL_T;
+}
+
+
+/*=gfunc gperf
+ *
+ * what: perform a perfect hash function
+ * general_use:
+ *
+ * exparg: name , name of hash list
+ * exparg: str , string to hash
+ *
+ * doc: Perform the perfect hash on the input string. This is only useful if
+ * you have previously created a gperf program with the @code{make-gperf}
+ * function @xref{SCM make-gperf}. The @code{name} you supply here must
+ * match the name used to create the program and the string to hash must
+ * be one of the strings supplied in the @code{make-gperf} string list.
+ * The result will be a perfect hash index.
+ *
+ * See the documentation for @command{gperf(1GNU)} for more details.
+=*/
+SCM
+ag_scm_gperf(SCM name, SCM str)
+{
+ char const * cmd;
+ char const * key2hash = ag_scm2zchars(str, "key-to-hash");
+ char const * gp_name = ag_scm2zchars(name, "gperf name");
+
+ /*
+ * Format the gperf command and check the result. If it fits in
+ * scribble space, use that.
+ * (If it does fit, then the test string fits already).
+ */
+ cmd = aprf(RUN_GPERF_CMD, gp_name, key2hash);
+ key2hash = shell_cmd(cmd);
+ if (*key2hash == NUL)
+ str = SCM_UNDEFINED;
+ else
+ str = AG_SCM_STR02SCM(key2hash);
+
+ AGFREE((void *)cmd);
+ AGFREE((void *)key2hash);
+ return str;
+}
+#endif
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * end of agen5/expGperf.c */