/*
* $Id: expGperf.c,v 4.15 2007/07/04 20:51:11 bkorb Exp $
*
* Time-stamp: "2007-07-04 11:18:51 bkorb"
* Last Committed: $Date: 2007/07/04 20:51:11 $
*
* 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.
* AutoGen copyright (c) 1992-2007 by 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 .
*/
#ifndef SHELL_ENABLED
SCM
ag_scm_make_gperf( SCM name, SCM hlist )
{
return SCM_UNDEFINED;
}
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_} 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 )
{
SCM newline = AG_SCM_STR2SCM("\n", (size_t)1);
char* pzName = ag_scm2zchars( name, "gperf name" );
char* pzList;
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.
*/
{
static int const makeGperfLine = __LINE__ + 2;
static char const* pzCleanup =
"(add-cleanup \"rm -rf ${gpdir}\")";
char* pzCmd = aprf( zMakeGperf, pzList, pzName );
/*
* Run the command and ignore the results.
* In theory, the program should be ready.
*/
pzList = runShell( pzCmd );
AGFREE( pzCmd );
if (pzList != NULL)
free( pzList );
if (pzCleanup != NULL) {
(void)ag_scm_c_eval_string_from_file_line(
pzCleanup, __FILE__, makeGperfLine );
pzCleanup = NULL;
}
}
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* pzCmd;
char* pzStr = ag_scm2zchars( str, "key-to-hash" );
char* pzName = 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).
*/
pzCmd = aprf( zRunGperf, pzName, pzStr );
pzStr = runShell( pzCmd );
if (*pzStr == NUL)
str = SCM_UNDEFINED;
else
str = AG_SCM_STR02SCM( pzStr );
AGFREE( pzCmd );
AGFREE( pzStr );
return str;
}
#endif
/*
* Local Variables:
* mode: C
* c-file-style: "stroustrup"
* indent-tabs-mode: nil
* End:
* end of agen5/expGperf.c */