diff options
author | kristaps <kristaps@cvs.openbsd.org> | 2009-04-06 20:30:41 +0000 |
---|---|---|
committer | kristaps <kristaps@cvs.openbsd.org> | 2009-04-06 20:30:41 +0000 |
commit | d6078dcec0f8d2f32163a0521bc99061d13833c3 (patch) | |
tree | 78c111539037b977ae903b756efaf6c36ed679e5 /usr.bin/mandoc/mdoc_hash.c | |
parent | e45f6a22f0833c27b75dbebe1b92e9a7c8f84cad (diff) |
Initial check-in of mandoc for formatting manuals. ok deraadt@
Diffstat (limited to 'usr.bin/mandoc/mdoc_hash.c')
-rw-r--r-- | usr.bin/mandoc/mdoc_hash.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/usr.bin/mandoc/mdoc_hash.c b/usr.bin/mandoc/mdoc_hash.c new file mode 100644 index 00000000000..73602bf2e0a --- /dev/null +++ b/usr.bin/mandoc/mdoc_hash.c @@ -0,0 +1,174 @@ +/* $Id: mdoc_hash.c,v 1.1 2009/04/06 20:30:40 kristaps Exp $ */ +/* + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "libmdoc.h" + +/* + * Routines for the perfect-hash hashtable used by the parser to look up + * tokens by their string-ified names (`.Fl' -> MDOC_Fl). The + * allocation penalty for this is 27 * 26 * sizeof(ptr). + */ + +void +mdoc_hash_free(void *htab) +{ + + free(htab); +} + + +void * +mdoc_hash_alloc(void) +{ + int i, major, minor, ind; + const void **htab; + + htab = calloc(27 * 26 * 3, sizeof(struct mdoc_macro *)); + if (NULL == htab) + return(NULL); + + for (i = 1; i < MDOC_MAX; i++) { + major = mdoc_macronames[i][0]; + assert((major >= 65 && major <= 90) || + major == 37); + + if (major == 37) + major = 0; + else + major -= 64; + + minor = mdoc_macronames[i][1]; + assert((minor >= 65 && minor <= 90) || + (minor == 49) || + (minor >= 97 && minor <= 122)); + + if (minor == 49) + minor = 0; + else if (minor <= 90) + minor -= 65; + else + minor -= 97; + + assert(major >= 0 && major < 27); + assert(minor >= 0 && minor < 26); + + ind = (major * 27 * 3) + (minor * 3); + + if (NULL == htab[ind]) { + htab[ind] = &mdoc_macros[i]; + continue; + } + + if (NULL == htab[++ind]) { + htab[ind] = &mdoc_macros[i]; + continue; + } + + assert(NULL == htab[++ind]); + htab[ind] = &mdoc_macros[i]; + } + + return((void *)htab); +} + + +int +mdoc_hash_find(const void *arg, const char *tmp) +{ + int major, minor, ind, slot; + const void **htab; + + htab = /* LINTED */ + (const void **)arg; + + if (0 == tmp[0] || 0 == tmp[1]) + return(MDOC_MAX); + if (tmp[2] && tmp[3]) + return(MDOC_MAX); + + if ( ! (tmp[0] == 37 || (tmp[0] >= 65 && tmp[0] <= 90))) + return(MDOC_MAX); + + if ( ! ((tmp[1] >= 65 && tmp[1] <= 90) || + (tmp[1] == 49) || + (tmp[1] >= 97 && tmp[1] <= 122))) + return(MDOC_MAX); + + if (tmp[0] == 37) + major = 0; + else + major = tmp[0] - 64; + + if (tmp[1] == 49) + minor = 0; + else if (tmp[1] <= 90) + minor = tmp[1] - 65; + else + minor = tmp[1] - 97; + + ind = (major * 27 * 3) + (minor * 3); + if (ind < 0 || ind >= (27 * 26 * 3)) + return(MDOC_MAX); + + if (htab[ind]) { + slot = htab[ind] - /* LINTED */ + (void *)mdoc_macros; + assert(0 == (size_t)slot % sizeof(struct mdoc_macro)); + slot /= sizeof(struct mdoc_macro); + if (mdoc_macronames[slot][0] == tmp[0] && + mdoc_macronames[slot][1] == tmp[1] && + (0 == tmp[2] || + mdoc_macronames[slot][2] == tmp[2])) + return(slot); + ind++; + } + + if (htab[ind]) { + slot = htab[ind] - /* LINTED */ + (void *)mdoc_macros; + assert(0 == (size_t)slot % sizeof(struct mdoc_macro)); + slot /= sizeof(struct mdoc_macro); + if (mdoc_macronames[slot][0] == tmp[0] && + mdoc_macronames[slot][1] == tmp[1] && + (0 == tmp[2] || + mdoc_macronames[slot][2] == tmp[2])) + return(slot); + ind++; + } + + if (NULL == htab[ind]) + return(MDOC_MAX); + slot = htab[ind] - /* LINTED */ + (void *)mdoc_macros; + assert(0 == (size_t)slot % sizeof(struct mdoc_macro)); + slot /= sizeof(struct mdoc_macro); + if (mdoc_macronames[slot][0] == tmp[0] && + mdoc_macronames[slot][1] == tmp[1] && + (0 == tmp[2] || + mdoc_macronames[slot][2] == tmp[2])) + return(slot); + + return(MDOC_MAX); +} + |