X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/df852be063ccaffc5f94728db7a3597ced2d375f..18756bee6a2b8aa06f001bce6843bce5b2dfb0b0:/unihash-mkstatic.c diff --git a/unihash-mkstatic.c b/unihash-mkstatic.c new file mode 100644 index 0000000..ba074e6 --- /dev/null +++ b/unihash-mkstatic.c @@ -0,0 +1,266 @@ +/* -*-c-*- + * + * $Id: unihash-mkstatic.c,v 1.1 2003/12/15 20:52:56 mdw Exp $ + * + * Build static universal hash tables + * + * (c) 2003 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: unihash-mkstatic.c,v $ + * Revision 1.1 2003/12/15 20:52:56 mdw + * New program to make fixed tables for universal hashing. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include "macros.h" +#include "mdwopt.h" +#include "quis.h" +#include "report.h" +#include "unihash.h" + +/*----- Main code ---------------------------------------------------------*/ + +#define BSCOL 72 + +static unsigned long getint(const char *p, unsigned long max, + const char *what) +{ + char *pp; + unsigned long x = strtoul(p, &pp, 0); + if (*pp || (max && x > max)) + die(EXIT_FAILURE, "bad %s `%s'", what, p); + return (x); +} + +static void version(FILE *fp) +{ + pquis(fp, "$, mLib version " VERSION "\n"); +} + +static void usage(FILE *fp) +{ + pquis(fp, "Usage: $ [-c] [-o FILE] [-g GUARD] [-i HEADER] [-s SYM]\n\ + [-k KEY]\n"); +} + +static void help(FILE *fp) +{ + version(fp); + putc('\n', stdout); + usage(fp); + fputs("\n\ +Emits a precomputed unihash_info structure for a given key.\n\ +\n\ +-h, --help Show this help text.\n\ +-v, --version Show the program's version number.\n\ +-u, --usage Show a terse usage message.\n\ +\n\ +-c, --c-source Emit a C source file rather than a header.\n\ +-k, --key=KEY Use KEY as the universal hashing key.\n\ +-g, --guard=GUARD Use GUARD as a multiple-inclusion guard constant.\n\ +-i, --include=HEADER Include HEADER at top of C source file.\n\ +-s, --symbol=SYM Name the generated table SYM.\n\ +-o, --output=FILE Write the output to FILE.\n\ +", stdout); +} + +int main(int argc, char *argv[]) +{ + uint32 key = 0xe07e5bd1; + unsigned flags = 0; + const char *sym = 0; + const char *inc = 0; + const char *guard = 0; + const char *file = 0; + FILE *fp; + unihash_info u; + int i, j, k; + +#define f_bogus 1u +#define f_ctab 2u + + ego(argv[0]); + + for (;;) { + static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "usage", 0, 0, 'u' }, + + { "output", OPTF_ARGREQ, 0, 'o' }, + { "c-source", 0, 0, 'c' }, + { "key", OPTF_ARGREQ, 0, 'k' }, + { "symbol", OPTF_ARGREQ, 0, 's' }, + { "include", OPTF_ARGREQ, 0, 'i' }, + { "guard", OPTF_ARGREQ, 0, 'g' }, + + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "hvu o:ck:s:i:g:", opts, 0, 0, 0); + + if (i < 0) + break; + switch (i) { + case 'h': + help(stdout); + exit(0); + case 'v': + version(stdout); + exit(0); + case 'u': + usage(stdout); + exit(0); + + case 'o': + file = optarg; + break; + case 'c': + flags |= f_ctab; + break; + case 's': + sym = optarg; + break; + case 'i': + inc = optarg; + break; + case 'g': + guard = optarg; + break; + case 'k': + key = getint(optarg, 0xffffffff, "key"); + break; + + default: + flags |= f_bogus; + break; + } + } + if ((flags & f_bogus) || optind != argc) { + usage(stderr); + exit(EXIT_FAILURE); + } + + /* --- Sort stuff out --- */ + + unihash_setkey(&u, key); + if (!sym) + sym = (flags & f_ctab) ? "uhi" : "UHI_INIT"; + + /* --- Start output --- */ + + if (!file) + fp = stdout; + else { + if (!(flags & f_ctab) && !guard) { + char *p; + const char *q; + if ((p = malloc(strlen(file) + 1)) == 0) + die(EXIT_FAILURE, "not enough memory"); + guard = p; + for (q = file; *q; p++, q++) { + if (isalnum((unsigned char)*q)) + *p = toupper((unsigned char)*q); + else + *p = '_'; + } + *p++ = 0; + } + if ((fp = fopen(file, "w")) == 0) + die(EXIT_FAILURE, "couldn't write `%s': %s", file, strerror(errno)); + } + + /* --- Dump out the first chunk of the file --- */ + + fprintf(fp, "\ +/* -*-c-*-\n\ + *\n\ + * Unihash table (key = %08lx) [generated]\n\ + */\n\ +\n", + (unsigned long)key); + + if (flags & f_ctab) { + if (inc) + fprintf(fp, "#include \"%s\"\n\n", inc); + else + fputs("#include \n\n", fp); + fprintf(fp, "unihash_info %s = { {\n", sym); + } else { + int n; + if (guard) + fprintf(fp, "#ifndef %s\n#define %s\n\n", guard, guard); + n = fprintf(fp, "#define %s { {", sym); + while (n < BSCOL) { + fputc('\t', fp); + n = (n + 8) & ~7; + } + fputc('\n', fp); + } + + /* --- Main output --- */ + + for (i = 0; i < N(u.s); i++) { + fputs(" {", fp); + for (j = 0; j < N(u.s[i]); j++) { + fputs(" {", fp); + for (k = 0; k < N(u.s[i][j]); k++) { + fprintf(fp, " 0x%08lx", (unsigned long)u.s[i][j][k]); + if (k < N(u.s[i][j]) - 1) { + fputc(',', fp); + if (k % 4 == 3) + fputs(flags & f_ctab ? "\n " : "\t\t\t\\\n ", fp); + } + } + if (j < N(u.s[i]) - 1) { + fputs(flags & f_ctab ? " },\n\n " : + " },\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n ", fp); + } + } + if (i < N(u.s) - 1) { + fputs(flags & f_ctab ? " } },\n\n" : + " } },\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n", fp); + } + } + + /* --- Done --- */ + + fputs(flags & f_ctab ? " } }\n} };\n" : + " } }\t\t\\\n} }\n", fp); + if (!(flags & f_ctab) && guard) + fputs("\n#endif\n", fp); + + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/