version 1.2, 2009/04/02 06:51:44 |
version 1.16, 2010/06/19 20:46:28 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> |
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the |
* purpose with or without fee is hereby granted, provided that the above |
* above copyright notice and this permission notice appear in all |
* copyright notice and this permission notice appear in all copies. |
* copies. |
|
* |
* |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* PERFORMANCE OF THIS SOFTWARE. |
|
*/ |
*/ |
|
#ifdef HAVE_CONFIG_H |
|
#include "config.h" |
|
#endif |
|
|
|
#include <sys/types.h> |
|
|
#include <assert.h> |
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
|
#include <limits.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <string.h> |
#include <string.h> |
|
|
|
#include "mandoc.h" |
#include "libmdoc.h" |
#include "libmdoc.h" |
|
|
|
static u_char table[27 * 12]; |
|
|
/* |
/* |
* Routines for the perfect-hash hashtable used by the parser to look up |
* XXX - this hash has global scope, so if intended for use as a library |
* tokens by their string-ified names (`.Fl' -> MDOC_Fl). The |
* with multiple callers, it will need re-invocation protection. |
* allocation penalty for this is 27 * 26 * sizeof(ptr). |
|
*/ |
*/ |
|
|
void |
void |
mdoc_hash_free(void *htab) |
mdoc_hash_init(void) |
{ |
{ |
|
int i, j, major; |
|
const char *p; |
|
|
free(htab); |
memset(table, UCHAR_MAX, sizeof(table)); |
} |
|
|
|
|
for (i = 0; i < (int)MDOC_MAX; i++) { |
|
p = mdoc_macronames[i]; |
|
|
void * |
if (isalpha((u_char)p[1])) |
mdoc_hash_alloc(void) |
major = 12 * (tolower((u_char)p[1]) - 97); |
{ |
|
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 |
else |
major -= 64; |
major = 12 * 26; |
|
|
minor = mdoc_macronames[i][1]; |
for (j = 0; j < 12; j++) |
assert((minor >= 65 && minor <= 90) || |
if (UCHAR_MAX == table[major + j]) { |
(minor == 49) || |
table[major + j] = (u_char)i; |
(minor >= 97 && minor <= 122)); |
break; |
|
} |
|
|
if (minor == 49) |
assert(j < 12); |
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); |
|
} |
} |
|
|
|
enum mdoct |
int |
mdoc_hash_find(const char *p) |
mdoc_hash_find(const void *arg, const char *tmp) |
|
{ |
{ |
int major, minor, ind, slot; |
int major, i, j; |
const void **htab; |
|
|
|
htab = /* LINTED */ |
if (0 == p[0]) |
(const void **)arg; |
|
|
|
if (0 == tmp[0] || 0 == tmp[1]) |
|
return(MDOC_MAX); |
return(MDOC_MAX); |
if (tmp[2] && tmp[3]) |
if ( ! isalpha((u_char)p[0]) && '%' != p[0]) |
return(MDOC_MAX); |
return(MDOC_MAX); |
|
|
if ( ! (tmp[0] == 37 || (tmp[0] >= 65 && tmp[0] <= 90))) |
if (isalpha((u_char)p[1])) |
|
major = 12 * (tolower((u_char)p[1]) - 97); |
|
else if ('1' == p[1]) |
|
major = 12 * 26; |
|
else |
return(MDOC_MAX); |
return(MDOC_MAX); |
|
|
if ( ! ((tmp[1] >= 65 && tmp[1] <= 90) || |
if (p[2] && p[3]) |
(tmp[1] == 49) || |
|
(tmp[1] >= 97 && tmp[1] <= 122))) |
|
return(MDOC_MAX); |
return(MDOC_MAX); |
|
|
if (tmp[0] == 37) |
for (j = 0; j < 12; j++) { |
major = 0; |
if (UCHAR_MAX == (i = table[major + j])) |
else |
break; |
major = tmp[0] - 64; |
if (0 == strcmp(p, mdoc_macronames[i])) |
|
return((enum mdoct)i); |
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); |
return(MDOC_MAX); |
} |
} |
|
|