Blame agen5/expGperf.c

Packit Service 96b5d3
/**
Packit Service 96b5d3
 * @file expGperf.c
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *  Create a perfect hash function program and use it to compute
Packit Service 96b5d3
 *  index values for a list of provided names.  It also documents how
Packit Service 96b5d3
 *  to incorporate that hashing function into a generated C program.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * @addtogroup autogen
Packit Service 96b5d3
 * @{
Packit Service 96b5d3
 */
Packit Service 96b5d3
/*
Packit Service 96b5d3
 *  This file is part of AutoGen.
Packit Service 96b5d3
 *  Copyright (C) 1992-2016 Bruce Korb - all rights reserved
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * AutoGen is free software: you can redistribute it and/or modify it
Packit Service 96b5d3
 * under the terms of the GNU General Public License as published by the
Packit Service 96b5d3
 * Free Software Foundation, either version 3 of the License, or
Packit Service 96b5d3
 * (at your option) any later version.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * AutoGen is distributed in the hope that it will be useful, but
Packit Service 96b5d3
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 96b5d3
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit Service 96b5d3
 * See the GNU General Public License for more details.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * You should have received a copy of the GNU General Public License along
Packit Service 96b5d3
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 96b5d3
 */
Packit Service 96b5d3
Packit Service 96b5d3
#ifndef SHELL_ENABLED
Packit Service 96b5d3
HIDE_FN(SCM ag_scm_make_gperf(SCM name, SCM hlist))
Packit Service 96b5d3
{
Packit Service 96b5d3
    return SCM_UNDEFINED;
Packit Service 96b5d3
}
Packit Service 96b5d3
Packit Service 96b5d3
HIDE_FN(SCM ag_scm_gperf(SCM name, SCM str))
Packit Service 96b5d3
{
Packit Service 96b5d3
    return SCM_UNDEFINED;
Packit Service 96b5d3
}
Packit Service 96b5d3
#else
Packit Service 96b5d3
Packit Service 96b5d3
/*=gfunc make_gperf
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * what:   build a perfect hash function program
Packit Service 96b5d3
 * general_use:
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * exparg: name , name of hash list
Packit Service 96b5d3
 * exparg: strings , list of strings to hash ,, list
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * doc:  Build a program to perform perfect hashes of a known list of input
Packit Service 96b5d3
 *       strings.  This function produces no output, but prepares a program
Packit Service 96b5d3
 *       named, @file{gperf_<name>} for use by the gperf function
Packit Service 96b5d3
 *       @xref{SCM gperf}.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *       This program will be obliterated as AutoGen exits.
Packit Service 96b5d3
 *       However, you may incorporate the generated hashing function
Packit Service 96b5d3
 *       into your C program with commands something like the following:
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *       @example
Packit Service 96b5d3
 *       [+ (shellf "sed '/^int main(/,$d;/^#line/d' $@{gpdir@}/%s.c"
Packit Service 96b5d3
 *                  name ) +]
Packit Service 96b5d3
 *       @end example
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *       where @code{name} matches the name provided to this @code{make-perf}
Packit Service 96b5d3
 *       function.  @code{gpdir} is the variable used to store the name of the
Packit Service 96b5d3
 *       temporary directory used to stash all the files.
Packit Service 96b5d3
=*/
Packit Service 96b5d3
SCM
Packit Service 96b5d3
ag_scm_make_gperf(SCM name, SCM hlist)
Packit Service 96b5d3
{
Packit Service 96b5d3
    static bool do_cleanup = true;
Packit Service 96b5d3
Packit Service 96b5d3
    char const * gp_nam = ag_scm2zchars(name, "gp nm");
Packit Service 96b5d3
    char const * h_list;
Packit Service 96b5d3
    SCM          nl_scm = scm_from_latin1_stringn(NEWLINE, (size_t)1);
Packit Service 96b5d3
Packit Service 96b5d3
    if (! scm_is_string(name))
Packit Service 96b5d3
        return SCM_UNDEFINED;
Packit Service 96b5d3
Packit Service 96b5d3
    /*
Packit Service 96b5d3
     *  Construct the newline separated list of values
Packit Service 96b5d3
     */
Packit Service 96b5d3
    hlist  = ag_scm_join(nl_scm, hlist);
Packit Service 96b5d3
    h_list = ag_scm2zchars(hlist, "hash list");
Packit Service 96b5d3
Packit Service 96b5d3
    /*
Packit Service 96b5d3
     *  Stash the concatenated list somewhere, hopefully without an alloc.
Packit Service 96b5d3
     */
Packit Service 96b5d3
    {
Packit Service 96b5d3
        char * cmd = aprf(MK_GPERF_SCRIPT, make_prog, gp_nam, h_list);
Packit Service 96b5d3
Packit Service 96b5d3
        /*
Packit Service 96b5d3
         *  Run the command and ignore the results.
Packit Service 96b5d3
         *  In theory, the program should be ready.
Packit Service 96b5d3
         */
Packit Service 96b5d3
        h_list = shell_cmd(cmd);
Packit Service 96b5d3
        AGFREE(cmd);
Packit Service 96b5d3
Packit Service 96b5d3
        if (h_list != NULL)
Packit Service 96b5d3
            free(VOIDP(h_list));
Packit Service 96b5d3
    }
Packit Service 96b5d3
Packit Service 96b5d3
    if (do_cleanup) {
Packit Service 96b5d3
        SCM_EVAL_CONST(MAKE_GPERF_CLEANUP);
Packit Service 96b5d3
        do_cleanup = false;
Packit Service 96b5d3
    }
Packit Service 96b5d3
Packit Service 96b5d3
    return SCM_BOOL_T;
Packit Service 96b5d3
}
Packit Service 96b5d3
Packit Service 96b5d3
Packit Service 96b5d3
/*=gfunc gperf
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * what:   perform a perfect hash function
Packit Service 96b5d3
 * general_use:
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * exparg: name , name of hash list
Packit Service 96b5d3
 * exparg: str  , string to hash
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * doc:  Perform the perfect hash on the input string.  This is only useful if
Packit Service 96b5d3
 *       you have previously created a gperf program with the @code{make-gperf}
Packit Service 96b5d3
 *       function @xref{SCM make-gperf}.  The @code{name} you supply here must
Packit Service 96b5d3
 *       match the name used to create the program and the string to hash must
Packit Service 96b5d3
 *       be one of the strings supplied in the @code{make-gperf} string list.
Packit Service 96b5d3
 *       The result will be a perfect hash index.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *       See the documentation for @command{gperf(1GNU)} for more details.
Packit Service 96b5d3
=*/
Packit Service 96b5d3
SCM
Packit Service 96b5d3
ag_scm_gperf(SCM name, SCM str)
Packit Service 96b5d3
{
Packit Service 96b5d3
    char const * cmd;
Packit Service 96b5d3
    char const * key2hash = ag_scm2zchars(str,  "key-to-hash");
Packit Service 96b5d3
    char const * gp_name  = ag_scm2zchars(name, "gperf name");
Packit Service 96b5d3
Packit Service 96b5d3
    /*
Packit Service 96b5d3
     *  Format the gperf command and check the result.  If it fits in
Packit Service 96b5d3
     *  scribble space, use that.
Packit Service 96b5d3
     *  (If it does fit, then the test string fits already).
Packit Service 96b5d3
     */
Packit Service 96b5d3
    cmd = aprf(RUN_GPERF_CMD, gp_name, key2hash);
Packit Service 96b5d3
    key2hash = shell_cmd(cmd);
Packit Service 96b5d3
    if (*key2hash == NUL)
Packit Service 96b5d3
        str = SCM_UNDEFINED;
Packit Service 96b5d3
    else
Packit Service 96b5d3
        str = scm_from_latin1_string(key2hash);
Packit Service 96b5d3
Packit Service 96b5d3
    AGFREE(cmd);
Packit Service 96b5d3
    AGFREE(key2hash);
Packit Service 96b5d3
    return str;
Packit Service 96b5d3
}
Packit Service 96b5d3
#endif
Packit Service 96b5d3
/**
Packit Service 96b5d3
 * @}
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * Local Variables:
Packit Service 96b5d3
 * mode: C
Packit Service 96b5d3
 * c-file-style: "stroustrup"
Packit Service 96b5d3
 * indent-tabs-mode: nil
Packit Service 96b5d3
 * End:
Packit Service 96b5d3
 * end of agen5/expGperf.c */